For most of my career, suggesting that a team aim for 100 percent test coverage earned an eye roll. It was taken as the mark of someone who cared more about a number than about shipping. The objection was reasonable at the time. It is not anymore. The economics that made full coverage a bad goal have changed, and 100 percent has gone from an unrealistic ideal to a sensible floor.

Why 100 percent used to be the wrong goal

The argument against full coverage was always about cost. The first eighty percent of coverage is cheap and valuable. The last stretch is where you end up writing awkward tests for error handlers and edge cases that rarely fire, and that work used to cost real engineering hours. So the pragmatic norm became “cover the important paths, aim for seventy or eighty percent, and spend the rest of your time shipping.” Given what tests cost to write, that was the right call.

AI changed the economics

Writing tests is exactly the kind of work AI-assisted coding does well. Describe the behavior and an agent will generate the unit and integration tests to cover it, including the tedious cases a person would skip. The expensive part of full coverage, the human hours, has mostly evaporated. When the marginal cost of covering that last stretch falls close to zero, the reasoning that justified leaving it uncovered falls apart with it.

Why the floor should now be full coverage

There is a second reason, and it is the more important one. Every untested line is a line no guardrail is watching. In a world where agents write a large share of your code, untested code is unreviewed code. Full coverage means that every line, at minimum, runs under a test. That is the baseline that makes the rest of your guardrails meaningful. It is hard to argue for less than all of it when the cost of all of it is no longer the obstacle.

Coverage is a floor, not a ceiling

Here is where I have to be straight with you, because the number invites a lie. One hundred percent line coverage does not mean your tests are good. A test can execute a line without asserting anything useful and still light up green on the coverage report. Coverage proves the code runs under test. It does not prove the behavior is correct.

The cheapest defense is to lint your tests the way you lint your code. Static analysis can flag tests that assert nothing, and an assertion-free test is worse than no test at all, because it trades a known gap for a false sense of safety. Make “every test asserts something meaningful” a rule your pipeline enforces, not a habit you hope for.

Grade the tests, not just the code

If you want to know whether your tests actually catch bugs, stop measuring the code and start measuring the tests. Mutation testing is the honest way to do it. It deliberately introduces small defects into your code, a flipped comparison, a deleted line, a changed constant, and checks whether your tests notice. A suite that stays green while the code is quietly broken is not protecting you, and mutation testing is what drags that failure into the light. It costs more to run than line coverage, which is exactly why it used to be rare, and exactly the kind of cost that cheap compute and AI now make affordable.

While you are at it, stop counting coverage from unit tests alone. Your integration and end-to-end tests exercise real paths through the assembled system, and measuring coverage against them tells you how much of your code is verified in something close to production conditions, not just in isolation. Line coverage as the floor, mutation testing to grade the tests, and coverage from your higher-level tests to confirm the real paths give you a far more honest picture of safety than any single number can.

Put an agent on the gaps

Here is where this gets genuinely fun. Finding undercovered code and writing tests for it is repetitive, well-defined work with a clear measure of success, which makes it close to ideal work for an agent. I build agents whose whole job is to hunt the weak spots in a test suite, the uncovered branches, the modules with thin assertions, the holes that mutation testing exposed, and to write the tests that close them. The agent proposes, your gates and your engineers review, and coverage climbs on its own. The work that once made full coverage feel impossible is now something you can hand to a tireless worker and simply review.

How to get there without misery

You do not retrofit full coverage in a weekend, and you should not try. Set a coverage floor at wherever you are today, and never let it drop. Require tests for all new code, which makes coverage climb on its own as you build. Use AI to backfill the gaps in the code you already have. Wire the floor into your CI gates so a change that lowers coverage cannot merge. Done this way, “100 percent” stops being a heroic project and becomes the quiet default.


Helping teams raise the bar on testing, and make full coverage the boring baseline rather than an impossible dream, is part of what I do as a fractional CTO with Artificer Innovations. If your coverage number has been stuck for a while, let’s talk.