SupercovCompare
← All comparisons

Code coverage · Comparison

Line coverage vs branch coverage

Line coverage asks whether each line ran; branch coverage asks whether each decision went both ways. A measured example, and why tools count differently.

What is the difference?

Line coverage asks whether each line ran. Branch coverage asks whether each decision went each way. A line can run while one of its branches never does, so 100% line coverage can hide untested paths. Track both. If you enforce one threshold, enforce branches.

A line that ran, a branch that did not

function label(user, fallback = 'Guest') {
  return user ? user.name : fallback;
}

One test calls label({ name: 'Ada' }). The return line ran, so line coverage is 100%. The function never returned fallback, and line coverage cannot say so. Branch coverage reports one branch missing on that line.

We measured this with Jest 30.5.2 and its default Babel provider, on a file with this function and one more: 5/5 lines, 6/7 branches. The missing branch is fallback.

Statement and function coverage

  • Statement coverage counts statements instead of lines. The two differ when one line holds several statements or one statement spans several lines.
  • Function coverage asks whether each function was called at all.

Istanbul-based tools report all four. Many others report lines and branches.

Tools do not count branches the same way

The same three tests on the same JavaScript file:

ToolLinesBranches
Jest, Babel provider5/56/7
Jest, V8 provider14/174/5
node --test, built-in coverage14/175/6

All three agree on which branch is missing. They disagree on how many branches and lines exist. Other languages differ again:

  • coverage.py counts a branch only when a line can jump to more than one next line. The Python version of label, on one line, reported 6/6 lines and 2/2 branches with fallback never returned.
  • go test -cover reports statements and has no branch metric.
  • JaCoCo counts branches in bytecode, where each condition of an && is its own jump.

Compare a branch percentage with the same tool’s earlier number, not with another tool’s.

What branch coverage still misses

if (signedIn && !expired) {

Two tests can take this if both ways without ever trying a signed-in session that has expired. Branch coverage is 100%. MC/DC is the metric that catches it.

Neither metric says whether a test checked the result. A test can run every branch and assert nothing.

Measure them on your tests

npx supercov -- npm test
npx supercov runs latest gaps

Supercov runs your existing test command and reports line, branch and MC/DC coverage per test, for JavaScript, TypeScript, Python, Go, Java, Kotlin, Rust and Ruby. On the JavaScript file above it reported 7/9 lines, 4/6 branches and 1/3 MC/DC conditions. Assertion coverage then shows which executed statements your tests check.

Example evidence: fixture source, commands and recorded results (JSON). Measured October 12, 2026 with Supercov 4.3.0. These small examples are not a performance benchmark or a general conformance test.