From qa-mutation-testing
Configures Stryker.NET for mutation testing of .NET Core / .NET Framework projects - installs `dotnet-stryker` global tool, scopes mutation to specific csproj, supports xUnit / NUnit / MSTest, authors `stryker-config.json` with thresholds, runs in CI. Use when a .NET test suite needs mutation-quality verification - closes the .NET ecosystem gap left by Stryker.NET being newer than the JS variant.
How this skill is triggered — by the user, by Claude, or both
Slash command
/qa-mutation-testing:stryker-net-mutationThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Per [stryker-net-intro][sni]:
Per stryker-net-intro:
"Stryker.NET offers you mutation testing for your .NET Core and .NET Framework projects. It allows you to test your tests by temporarily inserting bugs."
Per stryker-net-intro, Stryker.NET joined the Stryker family in 2018 as the .NET ecosystem mutation testing answer.
dotnet tool install -g dotnet-stryker
Per-project (recommended for CI determinism):
dotnet new tool-manifest
dotnet tool install dotnet-stryker
# From the test project directory
cd MyApp.Tests
dotnet stryker
The first run discovers the test framework, reports baseline coverage, then mutates and re-tests.
stryker-config.json{
"$schema": "https://raw.githubusercontent.com/stryker-mutator/stryker-net/master/src/Stryker.Core/Stryker.Core/stryker-config-schema.json",
"stryker-config": {
"project": "../MyApp/MyApp.csproj",
"test-projects": ["MyApp.Tests.csproj"],
"mutation-level": "Standard",
"thresholds": { "high": 80, "low": 60, "break": 50 },
"concurrency": 4,
"reporters": ["progress", "html", "cleartext"]
}
}
mutation-level controls how aggressive mutations are:
Basic (fewest mutators)Standard (default, recommended)AdvancedComplete (most mutators; slowest)For multi-project solutions:
dotnet stryker --solution path/to/MyApp.sln
Stryker.NET discovers all test projects and mutates the production projects each test references.
- uses: actions/setup-dotnet@v4
with: { dotnet-version: '8.x' }
- run: dotnet tool restore
- run: dotnet stryker --break-at 50
- uses: actions/upload-artifact@v4
if: always()
with:
name: stryker-net-report
path: StrykerOutput/
Reports land under StrykerOutput/<timestamp>/reports/mutation-report.html.
Common mutators include:
| Mutator | Example |
|---|---|
| Arithmetic operator | + → -, * → / |
| Conditional boundary | < → <=, > → >= |
| Conditional negation | !x → x |
| Logical operator | && → || |
| Equality | == → != |
| Return value | return foo() → return null / return "" / return 0 |
| Statement removal | Foo(); → ; |
| String literal | "x" → "" |
A surviving mutant means the test suite doesn't distinguish the original behavior from the mutated one.
| Anti-pattern | Why it fails | Fix |
|---|---|---|
| Running on the entire solution every PR | Long runtime; team disables. | Scope to changed projects via --project. |
mutation-level: Complete from day one | Slowest mode; many irrelevant mutants. | Start Standard; promote to Complete for critical libraries. |
| Ignoring "no coverage" mutants in the report | Untested code; mutation testing can't measure it. | Add tests OR exclude those files via --mutate. |
Skipping --break-at in CI | Mutation score regressions slip through. | Set --break-at to baseline + small headroom (Step 5). |
| Running against a Debug build | Slower; some mutators behave differently. | Run against Release build for CI gates. |
stryker-mutation - JS sibling
with the same Stryker model.pitest-mutation,
mutmut-mutation,
mull-mutation - per-language
alternatives.mutation-survivor-explainer - agent for surviving-mutant analysis.npx claudepluginhub testland/qa --plugin qa-mutation-testingProvides a checklist for code reviews covering functionality, security, performance, maintainability, tests, and quality. Use for pull requests, audits, team standards, and developer training.