Mutation

Equivalent mutants

Some mutants produce the same observable behaviour as the original program. No test can kill them because there is no difference to detect. These are equivalent mutants, and they inflate the survivor count without representing real test gaps.

Why equivalent mutants exist

A mutation like replacing x + 0 with x - 0 changes the bytecode but not the result. The mutant is alive but unkillable. Other examples:

ExampleWhy it is equivalent
Negating a variable that is always zerox and -x are both 0
Removing a print() call in code where output is not testedNo oracle checks stdout
Changing a comparison in a branch that is never reachedDead code, no observable effect

Every mutation testing tool has this problem. Vary uses heuristics to identify likely-equivalent mutants so they do not distort your score.

Suspicion heuristics

The equivalence analyzer scores each surviving mutant with multiple independent signals:

HeuristicConfidenceWhat it detects
bytecode_identical1.0Mutant bytecode is identical to original (already flagged by bytecode comparison)
trivial_arithmetic0.85Identity-preserving arithmetic: x + 0, x * 1, x - 0 patterns
dead_branch0.7Mutant survived with zero execution time (code path never reached)
semantic_noop0.6Statement removal of side-effect-only calls like print() or log()
untested_path0.4Mutant is in a code region with no test coverage at all

The overall confidence is the maximum signal confidence. Multiple signals reinforce the diagnosis but do not stack numerically.

Confidence levels and recommendations

ConfidenceRecommendation
0.9 to 1.0Quarantine automatically (almost certainly equivalent)
0.6 to 0.89Review recommended, likely equivalent but worth checking
0.4 to 0.59Investigate: may be a real test gap in untested code

Auto-quarantine

Use --auto-quarantine <threshold> to automatically quarantine mutants above a confidence level:

vary mutate src/ --auto-quarantine 0.9

This quarantines high-confidence equivalent mutants without manual review. Quarantined mutants are excluded from the mutation score and survivor lists. They are stored in .vary/equivalent-mutants.json and can be reviewed or restored:

vary mutate src/ --list-quarantined
vary mutate src/ --unquarantine "mutant-id"

Impact on scoring

Equivalent-likely mutants affect the actionable survivor rate but not the kill rate:

MetricIncludes equivalent-likely?
Kill rateNo (denominator includes them)
ObservabilityNo
Actionable survivor rateNo (subtracted from survivors)

The actionable survivor rate is the metric to watch: it excludes likely-equivalent mutants so you focus on survivors worth investigating.

What to do next

PageTopic
InfrastructureQuarantine management, policy gates, CLI reference
Lie detectionFind tests that pass but check nothing
Advanced overviewHow equivalent mutant handling fits the six-pillar model
← Infrastructure
Strict mode →