mutation-testing
Skill0 starsChanged 3 months agoMITView on GitHub
This skill should be used when the user asks "are our tests actually good", "is 100% coverage meaningful", "what is mutation testing", "how do I measure test quality", "which tests are worthless", or is setting a coverage target or reviewing a test suite that passes while bugs still ship. Covers whether existing assertions detect bugs. For testing code with no known correct output use `metamorphic-testing`.
30 other projects use a version of this.
Adopted by
Most recently taken up by
- camunda/camundatheir own version, first seen Nov 8, 2026
- DnsQueen/orcinus-skillstheir own version, first seen Nov 8, 2026
- Integralist/agent-skillstheir own version, first seen Nov 1, 2026
- shangyiy/life-kittheir own version, first seen Nov 1, 2026
- Hakkadaikon/hymmetheir own version, first seen Oct 26, 2026
- proffesor-for-testing/agentic-qetheir own version, first seen Oct 25, 2026
Used with
Projects with it also use domain-modeling, code-review and 1 more.
Other files people use alongside this one.
Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
GoogleSkilldomain-modeling
Build and sharpen a project's domain model. Use when the user wants to pin down domain terminology or a ubiquitous language, record an architectural decision, or when another skill needs to maintain the domain model.
Also in 3 projects that use this
GoogleSkillcode-review
Adversarial systems, concurrency, memory-model, and architecture code review protocol. Use this skill whenever asked to review code, PRs, diffs, or branches in Filament.
Also in 5 projects that use this
MicrosoftSkillgrill-with-docs
Grilling session that challenges your plan against the existing domain model, sharpens terminology, and updates documentation (CONTEXT.md, ADRs) inline as decisions crystallise. Use when user wants to stress-test a plan against their project's language and documented decisions.
Also in 3 projects that use this
Other versions30 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 30
- metabase/metabase★ 50ksame name
- recharts/recharts★ 28ksame name
- camunda/camunda★ 4.4ksame name
- ThibautBaissac/rails_ai_agents★ 665same name
- proffesor-for-testing/agentic-qe★ 524same name
- s3s-project/s3s★ 315same name
- jvm-skills/jvm-skills★ 140same name
- Amplicode/spring-skills★ 126same name
- GGGODLIN/gggodlin-cc-harness★ 73same name
- Integralist/agent-skills★ 23same name
20 more not listed
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository29 other files it gives its agents.
- algorithmic-complexity-attacksSkill
- cache-stampedeSkill
- clocks-and-timeSkill
- code-hotspotsSkill
- connascenceSkill
- connection-poolingSkill
- consistent-hashingSkill
- coordinated-omissionSkill
- cyclomatic-complexitySkill
- database-queuesSkill
- dependency-confusionSkill
- expand-contractSkill
- floating-pointSkill
- hyrums-lawSkill
- index-designSkill
- isolation-anomaliesSkill
- keyset-paginationSkill
- metamorphic-testingSkill
- module-depthSkill
- mvcc-and-bloatSkill
- parse-dont-validateSkill
- query-plansSkill
- queueing-and-utilizationSkill
- retry-amplificationSkill
- start-hereSkill
- tail-latencySkill
- unicode-pitfallsSkill
- universal-scalability-lawSkill
- write-amplificationSkill
The file
We split this skill into the rules it gives an agent
4 rules. 0 are common, 4 are distinctive, and 0 are very specific to this project.
0
Common
Most of the 27 edited versions we read keep these.
4
Distinctive
This author's own choices. Worth a look.
0
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 24
Run the test suite.
- Distinctive: line 25
If a test fails, the mutant is killed, meaning the tests detect that error.
- Distinctive: line 26
If all tests pass, the mutant survived, meaning that line can be wrong and nothing notices.
- Distinctive: line 70
Do not target 100%. Equivalent mutants make it unreachable, and chasing it produces tests asserting implementation details.
“Common” is measured: kept by at least 6 in 10 of the 27 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Mutation testing
The problem with coverage
Line coverage measures which lines ran, not which lines were checked. A test suite calling every function and asserting nothing scores 100%.
def test_calculate():
calculate(10, 5) # 100% coverage of calculate(), zero assertionsBranch coverage is better and has the same flaw. Coverage is a necessary condition, not a sufficient one: low coverage proves tests are missing, high coverage proves nothing.
Mutation testing answers the actual question: if the code were wrong, would a test fail?
How it works
- Make a small change to the source, a mutant:
>becomes>=,+becomes-, a boolean is negated, a return value becomes null, a statement is deleted. - Run the test suite.
- If a test fails, the mutant is killed, meaning the tests detect that error.
- If all tests pass, the mutant survived, meaning that line can be wrong and nothing notices.
Mutation score = killed mutants / total mutants
A surviving mutant is a precise, actionable statement: this exact change breaks nothing. Either a test is missing, or the code is dead.
Reading the output
Each surviving mutant is one of three findings:
| Finding | Meaning | Action |
| Missing assertion | The code runs but nothing checks the result | Add the assertion. This is the common case and the valuable one |
| Dead or unreachable code | The mutant cannot change behavior because nothing depends on it | Delete the code |
| Equivalent mutant | The mutation produces genuinely identical behavior, for example i < n versus i != n in a loop guaranteed to reach n | Nothing to fix. This is the tool's irreducible false-positive rate |
Equivalent mutants are undecidable in general, so no tool eliminates them. They typically account for a few percent of survivors. Suppress them explicitly rather than pretending the score can reach 100%.
Tools
| Language | Tool |
| Java | PIT (pitest), the most mature |
| Python | mutmut, cosmic-ray |
| JS/TS | Stryker |
| C# | Stryker.NET |
| Go | go-mutesting, ooze |
| Rust | cargo-mutants |
| PHP | Infection |
Making it practical
Mutation testing is expensive: the test suite runs once per mutant, so a suite taking 2 minutes with 500 mutants is 16 hours naively.
Controls that make it usable:
- Run on the diff only. Mutate changed lines in a PR, not the whole codebase. This is the single change that makes it viable, and most tools support it (
pitestincremental analysis, Stryker--since). - Scope to critical modules. Payment calculation, permission checks, and pricing deserve it. A CRUD controller does not.
- Run nightly, not per commit, for the full suite.
- Use test selection, where the tool runs only tests covering the mutated line. Every mature tool does this by default.
- Fail the build on new survivors, not on an absolute score. A ratchet works where a target does not.
Interpreting the score
Do not target 100%. Equivalent mutants make it unreachable, and chasing it produces tests asserting implementation details.
| Score | Reading |
| Below 50% | Tests largely execute code without checking it |
| 60-80% | Typical for a healthy suite |
| Above 90% | Strong, usually only worth reaching in critical modules |
The score matters less than the survivor list. Read the survivors in the code that matters and fix those.
Why the survivors are the point
A surviving mutant in a pricing function is a statement that pricing can silently change and the suite stays green. That is a concrete, prioritized bug report about the test suite, which coverage percentages never provide.
It also finds a specific failure mode nothing else catches: tests that assert the wrong thing. A test asserting result is not None passes for every mutant that changes the value, and mutation testing surfaces exactly that.
Relationship to other measures
- Coverage finds untested code. Mutation testing finds unchecked code. Run coverage first, since mutation testing on uncovered lines only reports that they are uncovered.
- Property-based testing generates inputs. Mutation testing evaluates assertions. They are complementary: property tests often kill mutants that example-based tests miss, because they assert invariants rather than specific values.
metamorphic-testinghelps where the correct output is unknown, which is the case mutation testing cannot help with, since it presumes assertions are possible.
Where not to use it
- Suites with flaky tests. A flaky test kills mutants at random and the score is noise. Fix flakiness first.
- Suites slower than a few minutes without diff scoping, where the feedback loop is too slow to act on.
- Generated code, glue code, and thin adapters, where survivors are mostly equivalent mutants.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

