Test Coverage
Test coverage measures how much of your code is actually exercised when the test suite runs. It's a useful diagnostic — it pinpoints code no test touches — but it's frequently misused as a quality target. The crucial distinction: coverage tells you what code ran, not whether your tests verified anything meaningful about it.
The healthy way to use coverage is as a flashlight, not a scoreboard: run it to find untested critical paths and error handlers, hold the line so coverage doesn't silently erode, and resist the urge to chase 100% by writing assertions that prove nothing.
TL;DR
- Coverage shows what's tested, not test quality.
- Aim for high coverage on critical paths, not everywhere.
- Don't chase 100% blindly.
- Use coverage to find untested code — especially error paths.
Quick Example
Generate a coverage report and read it for gaps, not for the headline number:
Core Concepts
Coverage metrics
- Line coverage — % of lines executed.
- Branch coverage — % of branches (if/else, ternaries) taken. The most revealing.
- Function coverage — % of functions called.
- Statement coverage — % of statements executed.
💡 Branch coverage matters most: 100% line coverage can still miss the
elseof a condition. A test can run a line without ever exercising both outcomes.
Limitations
- High coverage ≠ good tests — code can execute without any assertion verifying it.
- Some code (trivial getters, debug helpers) isn't worth testing.
- The signal is where to look, not how good the suite is.
Running Coverage
JavaScript (Jest / Vitest)
Python (pytest-cov)
Coverage in CI
Set a floor and fail builds that drop below it:
Track trends over time with Codecov or Coveralls, and fail when coverage decreases:
Finding & Excluding Code
Use the HTML report to spot red (unexecuted) lines and untaken branches — especially error-handling paths, which tests routinely miss:
Exclude genuinely untestable code explicitly:
Best Practices
- Target tiers, not a flat number — critical business logic ~95%, general code ~80%, utilities lower.
- Watch branch coverage — it surfaces missed conditional paths.
- Gate CI on a floor and alert on decreases, not just an absolute.
- Read the report to find untested error paths — don't just glance at the percentage.
- Exclude debug/type-only code rather than writing hollow tests for it.
Common Mistakes
Writing tests just to hit 100%
Treating the percentage as quality
FAQ
What coverage percentage should I aim for?
There's no magic number. A common practice is ~80% as a CI floor for general code, ~90–95% for critical business logic, and lower for utilities/glue. But the percentage is a means, not the goal — covering the right code (core logic, branches, error paths) well matters far more than a high overall figure padded with trivial tests.
Why isn't 100% coverage a good goal?
Because the last stretch usually means writing low-value tests for trivial or defensive code, and 100% line coverage still doesn't guarantee your assertions are meaningful — code can run without being verified. Chasing 100% trades real effort for a vanity metric and can even encourage hollow tests. Aim for high coverage of what matters, not totality.
What's the difference between line and branch coverage?
Line coverage counts which lines executed; branch coverage counts whether each decision path (both the if and the else) was taken. Branch coverage is stricter and more informative — you can have 100% line coverage while never testing the false branch of a condition. Prefer branch coverage as your primary metric for conditional-heavy code.
Does high coverage mean my tests are good?
No. Coverage only measures what code ran during tests, not whether the tests checked the right things. A suite can hit 95% coverage with weak or missing assertions. To gauge whether tests actually catch regressions, look at assertion quality and consider mutation testing, which deliberately introduces bugs to see if your tests notice.
Related Topics
- Unit Testing — Test fundamentals
- TDD — Tests drive design
- CI/CD — Automated coverage gates
- Jest · Pytest — Built-in coverage
- Code Quality — Coverage in context