JS Guide
HomeQuestionsTopicsCompaniesResources
BookmarksSearch

Built for developers preparing for JavaScript, React & TypeScript interviews.

ResourcesQuestionsSupport
HomeQuestionsSearchProgress
HomeTopicstestingCode Coverage Metrics
PrevNext
testing
intermediate
12 min read

Code Coverage Metrics

branch-coverage
code-coverage
istanbul
jest
quality
testing-metrics
thresholds
vitest

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.

Key Points

1Four Coverage Types

Line coverage tracks executed lines, branch coverage tracks conditional paths, statement coverage counts individual statements, and function coverage tracks called functions.

2Branch Coverage Priority

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.

3Coverage Does Not Equal Correctness

100% coverage does not guarantee bug-free code. Tests can execute lines without meaningful assertions, inflating coverage while missing actual defects.

4Practical Threshold Strategy

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.

What You'll Learn

  • Explain the difference between line, branch, statement, and function coverage
  • Interpret coverage reports to identify untested code paths
  • Set meaningful coverage thresholds and enforce them in CI
  • Articulate why high coverage does not guarantee code correctness

Deep Dive

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.

The Four Coverage Metrics

  1. 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.

  2. 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.

  3. 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.

  4. 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.

Interpreting Coverage Reports

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.

Setting Coverage Targets

Common industry targets are 70-80% for application code and 90%+ for shared libraries or utilities. However, coverage targets should be pragmatic:

  • Enforce thresholds in CI to prevent coverage from dropping (ratcheting approach)
  • Focus new code coverage on business-critical paths, not arbitrary percentage goals
  • Use per-file thresholds for critical modules rather than a single global number

You can configure thresholds in Jest or Vitest config:

JavaScript
// jest.config.js or vitest.config.ts
coverageThreshold: {
  global: { branches: 80, functions: 80, lines: 80, statements: 80 }
}

Why 100% Coverage is Misleading

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.

Coverage as a Tool, Not a Goal

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.

Practical Tips

  • Run coverage in CI and fail builds if coverage drops below the threshold
  • Ignore generated files, type definitions, and configuration in coverage reports
  • Review the branch coverage column specifically when reviewing test quality
  • Use coverage diff tools to ensure new PRs maintain or improve coverage

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.

Learn These First

Unit Testing Fundamentals

beginner

Test Organization and Structure

beginner

Continue Learning

Testing Strategy for Large Applications

advanced

Integration Tests vs Unit Tests

intermediate

Practice What You Learned

What is code coverage and how do you interpret coverage reports?
mid
coverage
Code coverage measures how much source code is executed by tests. Metrics include lines, statements, branches, and functions. High coverage doesn't guarantee quality - focus on testing critical paths and edge cases rather than chasing 100%.
Previous
Unit Testing Fundamentals
Next
End-to-End Testing
PrevNext