Test Coverage Metrics
Test coverage metrics quantify how much of the code a test suite exercises, useful as a signal but dangerous as a target.
Definition
Test coverage metrics measure the proportion of code touched by tests: line coverage (executed lines), branch coverage (taken decision outcomes), and path coverage (executed control-flow paths). They are computed by instrumenting execution and recording which units ran. Coverage reveals untested regions, but it says nothing about whether assertions are meaningful, so it is a map of blind spots rather than a measure of quality.
Context and scope
Used in CI to spot untested code and to set minimum bars, always interpreted alongside the strength of the tests themselves.
Common misconceptions
- High coverage means well-tested code — a test can execute every line and assert nothing, or assert the wrong thing
- 100 percent coverage is the goal — chasing the last percent drives tests of trivial code and rewards superficial assertions
- Coverage is useless — as a lint for untested regions it is valuable; only as a quality target is it misleading
Anti-patterns
- Adding assertion-free tests solely to raise the coverage number
- Excluding hard modules from coverage measurement and reporting inflated totals
- Blocking builds on a fixed coverage threshold regardless of which files changed
Related concepts
Related examples
Authoritative source
What it is
Coverage measurement instruments the program so each executed statement or branch is recorded during a test run. Line coverage counts executed lines over total lines; branch coverage counts taken outcomes over total possible outcomes; path coverage attempts the much larger space of control-flow paths. Each metric answers “what did the tests run” and is blind to “what did the tests check”.
Why it matters
Coverage is a cheap, automatic way to find code nobody tests — the modules where a change can ship with no safety net. Used this way it directs test effort precisely. Used as a score, it backfires: developers write tests that touch lines without asserting behaviour, and the metric rises while the suite protects nothing. The gap between executed and verified is where bugs hide.
How to use it well
Track coverage to find untested regions and review those, rather than to celebrate a number. Set a modest floor that prevents regression, and prefer diff coverage — coverage of the code actually changed — as a merge gate, since it scales with the change rather than the repository. Combine it with mutation testing or assertion review when you need evidence that the tests actually check behaviour.