Code coverage · Comparison
MC/DC vs branch coverage
Branch coverage asks whether a decision went both ways. MC/DC asks whether each condition changed the result on its own. One example in four languages.
What is the difference?
Branch coverage asks whether each decision went both ways. MC/DC asks whether
each condition inside the decision was shown, on its own, to change the
result. For a decision with one condition they need the same tests. They
differ when a decision joins conditions with && or ||.
One line, two answers
if (signedIn && !expired) {
return true;
}
return false;
Two tests: a signed-in session that is not expired gets true, and a
signed-out session gets false.
The if went both ways, so branch coverage is 100%. The two tests also show
that signedIn matters: it is the only input that changed, and the result
flipped.
Nothing shows that expired matters. Delete && !expired and both tests
still pass. MC/DC is 1 of 2 conditions. A third test, signed in and expired,
completes it.
How the criteria compare
| Criterion | Question | Tests for a && b && c |
|---|---|---|
| Line or statement | Did it run? | 1 |
| Branch (decision) | Did the decision go both ways? | 2 |
| MC/DC | Did each condition change the result on its own? | 4 |
| Multiple condition | Was every combination tried? | 8 |
MC/DC needs at least one more test than there are conditions. Trying every combination doubles with each condition added. MC/DC comes from avionics, where DO-178C requires it for the most critical software.
What tools report for that line
We ran the same check and the same two tests in four languages:
| Tool | Result for the decision |
|---|---|
| Jest 30.5.2, Babel provider | 4/4 branches |
| coverage.py 7.16.2 | 2/2 branches |
go test -cover, Go 1.27.1 | 100% of statements; no branch metric |
| JaCoCo 0.8.15 | 3/4 branches |
| Supercov 4.3.0, all four | branches covered; !expired not shown |
JaCoCo comes closest because it counts bytecode: javac compiles && into
one conditional jump per condition, and the expired side of the second jump
was never taken. That finds this gap. It still shows that each jump happened, not that a
condition changed the result on its own.
Which one to use
Branch coverage is enough for code whose decisions are single conditions. Use MC/DC where decisions combine conditions: access checks, pricing rules, feature flags, validation. Use it where a standard asks for it.
Measure MC/DC on your tests
npx supercov -- npm test
npx supercov runs latest gaps
Supercov runs your existing test command and measures line, branch and MC/DC coverage for JavaScript, TypeScript, Python, Go, Java, Kotlin, Rust and Ruby. For each gap it names the condition and the missing case. The MC/DC guide walks through an example.
New to the simpler metrics? See line coverage vs branch coverage.
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.