Coverage measures which code ran during your tests. A team should not aim for 100%. Coverage is a signal, not a goal.
Coverage tools count four things:
- statements
- lines
- functions
- branches: both sides of each
ifor?:
The tool collects coverage by instrumenting the code. This means it adds hidden counters to your code before the tests run. You get it with jest --coverage or Vitest's coverage option.
Branch coverage tells you the most. Line coverage only asks "did this line run?". But one line can hold two paths, like price > 100 ? price * 0.9 : price. A single test runs the line, so line coverage shows 100%. Branch coverage still shows the other path never ran.
Coverage shows what is not tested, which helps you find gaps. It doesn't show that code is tested well. A test can run a line without asserting anything about it. So 100% coverage doesn't mean bug-free.
Chasing 100% leads to low-value tests of trivial code. It also leads to tests coupled to implementation.
A healthy approach:
- Treat coverage as a signal, not a goal.
- Look at uncovered branches in important code.
- Maybe set a reasonable threshold in CI to stop big drops.
- Judge tests by the confidence they give.
- Coverage counts statements, lines, functions and branches that ran.
- Coverage shows untested code, not how good the tests are.
- 100% coverage does not mean the code is bug-free.
- Chasing 100% creates low-value tests.
- Use coverage as a signal. Branch coverage tells the most, because it shows paths that line coverage misses.