Coverage measures which lines or branches your tests execute. It is a useful signal for finding untested code, but it says nothing about whether the tests assert the right thing, so treating it as a target produces tests that run code without checking behavior.
Before you start
You should be comfortable with tests and a coverage tool. This article covers what coverage does and does not mean.
Step-by-step walkthrough
Step 1: Treat line coverage as a map
Line coverage shows which lines ran, which helps spot whole modules with no tests. It does not show whether the result was correct, so a test that calls a function and asserts nothing can still raise coverage.
Step 2: Prefer branch coverage for conditionals
Branch coverage tracks whether both sides of each condition ran, which is more meaningful than line coverage for logic with if and ternaries. Adding a branch target encourages tests for the else path instead of only the happy path.
Step 3: Do not chase a number
A coverage threshold can be a floor that catches regressions, but pursuing 100% leads to tests that exercise code without assertion or that test trivial code. Coverage of critical logic is what matters; the percentage is a proxy, not the goal.
Worked scenario
The test raises coverage without asserting behavior.
test('does not crash', () => {
processOrder({ id: 'o-1', total: 10 }); // no assertion: coverage only
});
test('computes total', () => {
expect(processOrder({ id: 'o-1', total: 10 }).total).toBe(10);
});Walk through the example
The first test executes processOrder and adds coverage but verifies nothing, so a regression that changes the result still passes. The second asserts the outcome and would fail if the computation broke. Both may count the same lines, but only one is a real test.
Common mistake
Chasing a coverage percentage, which incentivizes assertion-free tests and coverage of getters. Another is excluding hard-to-test code from the report to hit a target, which hides the real gap.
Verify the behavior
Introduce a bug in a covered line and confirm a real test fails; if it does not, the coverage was hollow. Compare branch coverage before and after adding a test for the else path. Review covered code for tests with no assertions.
Interview exercise
Can you have high coverage and still have poor tests?
Answer and reasoning
Yes. Coverage only records that code ran, not that the result was checked. A suite of tests that call functions without asserting their output can reach high coverage while catching almost nothing. The quality comes from meaningful assertions on behavior, which coverage cannot measure.
Continue learning
Compare assertions in Behavior assertions and confidence in Mutation testing. Read the Martin Fowler on test coverage and try the Testing interview questions.