Summary
cargo-mutants is a mutation testing tool for Rust. It mutates source code, runs the test suite, and reports whether tests catch the changes (mutants are "caught" or "missed"). Its mutation operators work at function granularity and through operator replacement; it does not substitute one method call for another. As a result, code that expresses policy as .min(), .max(), .clamp(), or .saturating_*() calls may receive no mutants at all for those decisions, making survival scores misleading. Its documentation stresses that the test suite must be reliable and non-flaky before results are meaningful, and provides flags for resuming work incrementally and limiting mutations to particular files.
Key Points
- Mutation testing requires a trustworthy baseline: flaky tests make cargo-mutants results meaningless, because a mutant can be reported as caught or missed at random.
cargo mutants --iterateskips mutants already found caught or unviable in earlier runs, accumulating results across sessions.- File scoping uses globs:
-f GLOB/--file GLOB, repeatable, with-e/--excludefor exclusions. - Configuration lives in
.cargo/mutants.tomlat the source tree root; the documented mechanism usesexclude_re/examine_reregex keys. - Mutation genres documented in v27 are:
- FnValue: replace an entire function body with a value guessed from its return type.
- Binary/unary operator replacement: swap or alter arithmetic/logic operators.
- There is no genre that substitutes one method call for another, e.g.
.min()is never changed to.max(). - A clamp buried inside a larger function is invisible to cargo-mutants; extracting it into its own named function makes it visible via the FnValue body-replacement genre.
--skip-calls/ theskip_callsconfig key prevents mutation of arguments to named calls; the tool has call-awareness for suppression but not for substitution.- A mutation score should not be read as "how strong the tests are" until you ask what mutant set the tool can generate against the specific code shape under test.