Build1 publisher3 min readPublished Updated
Supercov's MC/DC count exposes an untested session-expiry check behind 100% branch coverage
Supercov measured a two-test JavaScript checkout suite at 100% branch coverage and 50% MC/DC, flagging an expiry check no test protected. A single added assertion closed that gap while line and branch coverage stayed exactly where they were.
The Engineer · Build desk
What happened
- The example canCheckout(signedIn, expired) function had two tests, one for a valid session and one for a signed-out visitor, and neither passed an expired session.
- Reducing the condition to signedIn alone left both tests passing, so the suite would have accepted an expired session without a single failure.
- Run through npx supercov -- npm test, the suite scored 100% on lines (3/3) and branches (2/2) and 50% on MC/DC (1/2).
- Supercov marked line 2 as PARTIAL, reporting that no witness pair showed !expired independently changing the decision result.
- After an agent added a signed-in, expired-session test, Supercov's diff showed MC/DC up 50 points with line and branch coverage unchanged.
Compiled by The EngineerSomething wrong?How this is made
Why it matters
- exposure Teams that gate merges on line or branch coverage can delete a session-expiry or auth guard and still ship a green build reporting 100%.
- constraint Closing an MC/DC gap proves a condition ran, so reviewers still have to confirm the new test asserts the denied outcome before trusting the higher number.
- decision An MC/DC threshold set on Supercov's counts has to be re-baselined before it can be applied to another coverage provider's output.
- cost Delegating gap-filling to an agent shifts the work into reviewing each generated assertion against the behaviour the code is meant to have.
MC/DC, short for Modified Condition/Decision Coverage, treats `signedIn && !expired` as one decision made of two conditions [5]. For each condition it looks for a pair of runs in which only that condition changes and the decision's result changes with it [5]. The valid-session test and the signed-out test form that pair for `signedIn` [6]. The valid-session run has no partner for `!expired`, because no run holds `signedIn` true while flipping `expired` [6]. Branch coverage asks only whether both return statements ran, and both did [1].
JavaScript complicates the count. When `signedIn` is false, `&&` never evaluates `!expired`, and the post says a tool has to keep that skipped condition distinct from a false one [7]. The exact witness rules depend on which form of MC/DC is being measured. The post points to Clang's coverage documentation for its masking approach [8]. For a two-condition decision, according to the post, the missing expired-session case is straightforward [8].
Adoption is a prefix on the existing test command. `npx supercov -- npm test` runs whatever follows the `--` as the project's test command, and `npx supercov runs latest gaps` lists what was not observed [9]. The post hedges its own numbers, and I'd count that in its favour. It calls them Supercov's counts for this file and says different tools count branches differently [11]. It also says ordinary branch or condition counters are not evidence that a condition independently changes a decision [11].
The fix was one test expecting `canCheckout(true, true)` to return false, added by a coding agent that left the application code unchanged [13]. The post's authors wrote the line I would underline at review: "Calling the function would exercise the condition; checking the result verifies that this input is denied checkout." [14] A test that called the function and asserted nothing would exercise the same condition and catch nothing [14]. With the assertion in place, MC/DC reaches 100% [1]. Deleting the expiry guard now fails the new test [16].
The post suggests handing gap selection to an agent with a prompt that begins "Measure code coverage with npx supercov and write one missing test. Only change tests." [17] I think "Only change tests" is the right constraint for a guard like this one. It holds the code fixed, so the new test has to state what the code should do. If the code were already wrong, the same constraint could lead an agent to assert the bug. The post tells readers to review the changed test and the before-and-after comparison [18].
The demonstration is a single two-condition function with three tests [2][15]. The post does not report run time or results on a larger codebase. For the 50% figure to carry over to a real auth module, its guards would need to be measured as decisions in the same way, and its tests would need to assert outcomes. In my context, I'd run the MC/DC pass first on the files holding auth and checkout guards. A missed condition there grants access or accepts an order. Elsewhere I'd keep branch coverage until the overhead is known.
What to watch
- Published run time and results from Supercov on a production-size JavaScript codebase, as opposed to a three-line function.
- How Supercov reports decisions with more than two conditions, where the post says witness rules depend on the MC/DC form being measured.
- Whether other JavaScript coverage providers add MC/DC counts, and whether their figures match Supercov's on the same suite.