Tool

Both suites say one hundred percent. Only one of them is evidence.

Branch coverage and MC/DC each report full coverage of their own criterion on the same decision. This injects a deliberate fault at a time and shows which suite notices, which is the only comparison that means anything.

The decision

Any boolean decision from your own code. The tool builds a branch coverage suite and an MC/DC suite for it, injects a fault at a time, and reports which suite notices.

Operators: && and || and ! , or the words and, or, not. Up to 8 conditions. A && B is the DO-178C worked example. Try (A || B) && C for a wider gap.
This calculator runs entirely in your browser. Nothing you type is sent anywhere unless you ask for the result by email at the bottom of the page.
What each suite catches
Branch coverage kills
44%
4 of 9 injected faults, on 2 tests
MC/DC kills
100%
9 of 9, on 3 tests
Equivalent mutants
0
No test set can ever kill these
Branch-adequate suites
3
All report 100 percent
Both suites report one hundred percent of their own criterion. The branch coverage suite kills 4 of 9 injected faults; the MC/DC suite kills 9. The reported number is the same and the evidence is not.
SuiteTestsFaults killed
Branch coverageA=T, B=T | A=F, B=F4 of 9
MC/DCA=T, B=T | A=T, B=F | A=F, B=T9 of 9
The branch pair shown is the weakest of the 3 that satisfy the criterion. Branch coverage gives no way to ask for a better one, and every one of them reports one hundred percent.
Every injected fault, and who noticed
The decision becomesThe faultBranch coverageMC/DC
A || BOperator replacement, one connector swappedsurviveskilled
AThe decision ignores every condition except Asurviveskilled
BThe decision ignores every condition except Bsurviveskilled
(A || !A) && BA stuck at truesurviveskilled
A && (B || !B)B stuck at truesurviveskilled
!A && BCondition A negatedkilledkilled
A && !BCondition B negatedkilledkilled
A && !A && BA stuck at falsekilledkilled
A && (B && !B)B stuck at falsekilledkilled
Survivors are listed first, because a surviving mutant is a located test gap rather than a statistic. Operators follow Just et al. (FSE 2014): operator replacement, condition negation, a decision that ignores conditions, and a condition stuck at a constant.
Send me this comparison

The decision and both suites go with it. If your coverage number is the thing being reported upward, this is the one page that shows what it is and is not evidence of.

Your inputs are included so the reply can be specific.

What one hundred percent catches, by criterion

Deliberately injected faults caught, on decisions where both suites report full coverage. The last row is the one to carry into a meeting.

DecisionFaults injectedBranch coverage catchesMC/DC catchesBranch suites that qualify
A && B94 of 9 (44%)9 of 9 (100%)3
A || B94 of 9 (44%)9 of 9 (100%)3
A && B && C146 of 14 (43%)14 of 14 (100%)7
(A || B) && C142 of 14 (14%)14 of 14 (100%)15
A && (B || C) && D194 of 19 (21%)19 of 19 (100%)39
A && B || C && D190 of 19 (0%)19 of 19 (100%)63

On A && B || C && D, branch coverage reports one hundred percent and catches none of the nineteen injected faults. The last column is why: many different pairs of tests satisfy the criterion, they perform very differently, and the criterion offers no way to ask for a good one.

A worked example

Start with A and B, which the tool opens on. Nine faults are injected: operators swapped, conditions negated, the decision reduced to a single condition, a condition stuck at a constant.

The branch coverage suite is two tests and catches four of the nine. Among the survivors are the two that matter most: a decision that ignores B, and a decision that ignores A. Those are the D = A bug from the DO-178C tutorial, alive and passing, under a suite reporting one hundred percent.

The MC/DC suite is three tests and catches all nine. One extra test, and every injected fault dies.

Then try (A or B) and C. Branch coverage now catches two of fourteen, and fifteen distinct pairs of tests all satisfy the criterion. And A and B or C and D is the one worth remembering: nineteen faults injected, branch coverage reports full coverage and catches none of them.

Enter A and not A for the other half of the argument. Two of its four mutants are equivalent: they produce a decision that behaves identically on every possible input, so no test anywhere can kill them. That is why a mutation score of one hundred percent is unreachable, and why the practice is to review the surviving mutant list on critical paths rather than to chase the number.

The arithmetic, so you can check it

Mutants come from the operators Just et al. found do most of the coupling work with real faults: operator replacement, condition negation, and the case where the decision ignores conditions. A mutant is killed when some test in the suite produces a different outcome for it than for the original.

A mutant killed by no test in the entire truth table is equivalent, and it is excluded from the denominator rather than counted as a miss. The branch suite is the weakest of the qualifying pairs, chosen by exhaustive search over every true row against every false row.

The honest limit

MC/DC reaching one hundred percent on every row of the reference table is a property of boolean decision mutants, not a general claim. Real programs fail in ways no operator here models: Just et al. found 17 percent of real faults couple to no mutant even in principle, dominated by algorithm rewrites, code deletion, and numerical handling. Inozemtseva and Holmes separately note that a mandate like DO-178B MC/DC may increase expenses without necessarily increasing quality. Both findings stand. What this tool shows is narrower and still worth knowing: on a single decision, two criteria reporting the same number are not equally good evidence.

What coverage does and does not predict is in what the research actually says, and the mechanism in coverage measures what ran, not what you checked. To generate the MC/DC set for your own decision, use the MC/DC generator.

Questions

Why does 100 percent branch coverage miss bugs?

Because branch coverage only requires the decision to come out true once and false once, which two tests satisfy however many conditions are involved. Those two tests can move several conditions at the same time, so a fault in any one of them can be masked by the others, and the coverage number is identical either way.

What is a mutant, and what does killing one mean?

A mutant is the same code with one small deliberate fault injected: an operator swapped, a condition negated, a condition stuck at a constant. The suite kills it if some test now fails. A surviving mutant is a located test gap, meaning the suite runs that code and does not check the behaviour that changed.

Do injected faults tell you anything about real bugs?

Yes, with a measured limit. Across 357 real faults and 230,000 mutants, Just et al. found a coupling relationship for 73 percent of real faults, and mutant detection tracked real fault detection more strongly than statement coverage did. They also found 17 percent of real faults couple to no mutant even in principle, so it is the best available proxy rather than truth.

Why compare against the weakest branch coverage suite?

Because the criterion gives no way to ask for a better one. Many different pairs of tests satisfy branch coverage on the same decision, they catch very different numbers of faults, and every one of them reports one hundred percent. Scoring the luckiest possible pair would flatter a criterion that cannot be steered toward it.

Can I reach a 100 percent mutation score?

Not in general. Equivalent mutants produce a program that behaves identically on every input, so nothing can kill them, and detecting them is undecidable in general. Prevalence across the literature runs 4 to 39 percent of all mutants. The useful practice is reviewing the surviving mutant list on critical paths rather than chasing the percentage.