Understanding the four types of code coverage (line, branch, statement, function), interpreting coverage reports, setting meaningful targets, and knowing why 100% coverage does not guarantee bug-free code.
Line coverage tracks executed lines, branch coverage tracks conditional paths, statement coverage counts individual statements, and function coverage tracks called functions.
Branch coverage is the most meaningful metric because it reveals untested conditional paths that line coverage misses, such as error handling branches and guard clauses.
100% coverage does not guarantee bug-free code. Tests can execute lines without meaningful assertions, inflating coverage while missing actual defects.
Enforce 70-80% thresholds in CI with a ratcheting approach that prevents coverage from dropping, focusing on business-critical paths rather than arbitrary percentage goals.
Code coverage measures how much of your source code is executed when your test suite runs. It is a quantitative metric that helps identify untested areas, but understanding what it actually tells you -- and what it does not -- is a key interview topic that separates junior from senior thinking.
Line coverage: The percentage of executable lines that were run during tests. This is the most commonly cited metric but also the most superficial -- a line can be "covered" even if the test does not assert anything meaningful about its output.
Branch coverage: The percentage of conditional branches (if/else, ternary, switch cases, logical operators) that were evaluated in both directions. This is more valuable than line coverage because it reveals untested paths. A function with an early if (!input) return null might have 100% line coverage if only the happy path is tested, but branch coverage would show the guard clause branch was never taken.
Statement coverage: Similar to line coverage but counts individual statements, including multiple statements on one line. In code like const x = a ? b : c; doSomething(x);, statement coverage counts both the assignment and the function call separately.
Function coverage: The percentage of declared functions that were called at least once. Low function coverage often indicates dead code or missing test cases for entire features.
Jest (with --coverage) and Vitest (with --coverage) generate reports using Istanbul/V8 under the hood. The HTML report color-codes lines: green (covered), yellow (partially covered branch), and red (not covered). The summary table shows percentages for each file across all four metrics. Focus on branch coverage as the most meaningful indicator -- it reveals logic paths that tests never exercise.
Common industry targets are 70-80% for application code and 90%+ for shared libraries or utilities. However, coverage targets should be pragmatic:
You can configure thresholds in Jest or Vitest config:
// jest.config.js or vitest.config.ts
coverageThreshold: {
global: { branches: 80, functions: 80, lines: 80, statements: 80 }
}100% coverage does not mean 100% correctness. Coverage tells you which code ran, not whether the assertions are meaningful. A test that calls a function but never checks the return value achieves coverage without catching bugs. Tests that only check the happy path inflate coverage numbers while missing edge cases.
The real value of coverage is identifying blind spots, not hitting a number. Use the uncovered lines report to find critical paths you forgot to test. The most dangerous code is code you think is tested but actually is not -- coverage reports make this visible.
Fun Fact
Istanbul, the most popular JavaScript coverage tool, was named after the city in Turkey because its creator thought code coverage felt like navigating a complex city map. Jest and Vitest both use Istanbul under the hood by default, though Vitest also supports V8's built-in coverage.