Skip to main content

The Coverage Number Climbs While the Costly Branch Stays Untested

A 94% coverage badge counts a trivial getter the same as the branch where a payment fails mid-flight. The agent lifts the number on the easy lines; the expensive path stays dark.

Updated 3 min readMarkdown

A PR landed at 94% coverage and I almost approved it on the badge alone. Then I looked at which 6% was uncovered: the charge-refund failure branch, the path that moves money when an external gateway rejects mid-flight. Every getter and formatter had a test. The one branch that could cost real money had none.

One number averages easy and risky together

Global coverage counts every executed line the same. A pure formatter, a data lookup, a trivial null check all contribute as much as the branch where an external call fails, a queue drops a job, or a payment reverses. The agent can lift the percentage by testing the cheap, deterministic code and leave the costly path untouched. The badge goes up. The risk does not move.

Where the coverage hides

Kind of code Easy to test Why it rarely carries the risk
Pure formatter / getter Deterministic, fixed happy input Failure consequence is near zero
Trivial null or empty check One mocked call, one assertion Branch costs almost nothing when wrong
Payment or refund failure Needs injected rejection, partial state Moves or loses money when broken
External dependency retry Requires a forced timeout or error Hides data loss behind a green test
Queue drop on failure Needs a poisoned-message setup Loses work with no visible error

The cheap rows are exactly where an agent reaches first: deterministic input, obvious expected output, a test that writes itself. The expensive rows need a failure you have to manufacture, and that is the work the badge never rewards.

Test the costly branch before reading the percentage

Before I look at the coverage number, I list the branches with a real cost: money movement, an external dependency failing, partial state after a crash, data loss on drop. Each one needs at least one test that forces the failure, not the success, and asserts what the caller sees and what state remains. The easy code can ride on existing coverage; there is no reason to manufacture extra tests just to move the decimal.

Targeted gates instead of one global threshold

A flat 90% gate rewards padding the easy side. It cannot tell a reviewer that the refund path has a test, only that enough lines were touched. Targeted checks on risky modules do what the badge cannot: a failure-path test exists, the error shape is asserted, the partial state is verified after the fault. Those questions fail loudly on the branch that hurts, regardless of how high the global number climbed.

Coverage is a floor for code you already understand, not proof that the dangerous path is safe. Which uncovered branch in your codebase would cost the most to fail, and does it have a test?

No comments yet. Be the first to comment.