Code coverage measures how much of your source code actually ran during your test suite. This lesson explains what coverage really tells you (and doesn't), and how to generate a coverage report with Jest.
What Code Coverage Measures
When you run Jest with --coverage, it instruments your source files to track exactly which lines, branches, functions, and statements were executed while your tests ran. The result is a report showing, for each file, what percentage of that code was actually exercised by at least one test.
Coverage tells you what code ran — it does not tell you whether the assertions checking that code were meaningful. A test with zero expect() calls that simply calls a function still counts as "covering" that function's lines.
The report breaks coverage down by file and by four different metrics: statements, branches, functions, and lines.
The Four Coverage Metrics
% Stmts — percentage of statements executed
% Branch — percentage of if/else, switch, ternary branches taken
% Funcs — percentage of functions called at least once
% Lines — percentage of executable lines run
Statement coverage counts individual JavaScript statements executed at least once.
Branch coverage is often the most revealing metric — it shows untested if/else paths.
Function coverage shows entirely untested functions, a strong signal of missing tests.
Line coverage is the most commonly cited number but the least precise of the four.
Code Coverage Cheat Sheet
Commands and concepts for working with Jest coverage.
Command / Term
Meaning
jest --coverage
Runs tests and generates a coverage report
% Stmts
Percentage of statements executed
% Branch
Percentage of conditional branches taken
% Funcs
Percentage of functions called
% Lines
Percentage of executable lines run
coverage/lcov-report/index.html
Interactive HTML report, browsable per file
Uncovered line markers
Red highlighting in the HTML report
Coverage Percentage Is Not the Same as Test Quality
100% coverage is achievable with tests that call every function but assert nothing meaningful about their behavior. Coverage answers "did this code run", not "is this code correct". Treat coverage as a tool for finding untested code, not as a proxy for overall test quality.
// This achieves 100% coverage of divide(), but tests nothing useful
test('calls divide', () => {
divide(10, 2); // no expect() at all!
});
This test would show green in a coverage report while verifying absolutely nothing.
Using Coverage to Find Untested Edge Cases
The most productive use of a coverage report is scanning for red (uncovered) lines and branches after writing what you believed was a thorough test suite — it often reveals an error-handling path, an edge case, or an entire function nobody thought to test.
Common Mistakes
Treating a high coverage percentage as proof the code is well-tested.
Writing tests specifically to inflate coverage numbers without meaningful assertions.
Ignoring branch coverage while focusing only on the more forgiving line coverage number.
Never actually opening the HTML coverage report to see which specific lines are untested.
Key Takeaways
Coverage measures which code ran during tests, across statements, branches, functions, and lines.
High coverage does not guarantee meaningful assertions or correct behavior.
Branch coverage often reveals more real gaps than line coverage alone.
Coverage reports are most useful for finding untested edge cases, not as a quality score.
Pro Tip
Open coverage/lcov-report/index.html in a browser after running jest --coverage at least once. Clicking into individual files and seeing exactly which lines are highlighted red is far more useful than staring at the terminal percentage summary.
You now understand what code coverage measures. Next, learn how to read and interpret a full coverage report.