Stryker.NET version: 4.16.0
OS: macOS 15 (arm64)
.NET SDK: 8.0.130
Test framework: xUnit 2.9.2 + Reqnroll (also reproduced with SpecFlow)
Summary
Span filters (File.cs{start..end}) in the mutate array of stryker-config.json are silently ignored. The exact same span passed via CLI -m works correctly.
Reproduction
Setup: a project under test with a line range (e.g. lines 61–64 of Codec.cs) that should be excluded from mutation. Character offsets for that range are 1981–2175 (note: spans are character indices per the docs — that part works fine via CLI).
Config route — NOT excluded:
stryker-config.json:
{
"stryker-config": {
"solution": "Wop.Sdk.sln",
"target-framework": "net8.0",
"mutation-level": "Advanced",
"mutate": ["!src/Wop.Sdk/Codec.cs{1981..2175}"]
}
}
Run: dotnet stryker → mutants inside the span are still created and tested (830 mutants tested; Codec.cs lines 61–64 mutants present in mutation-report.json).
CLI route — excluded correctly:
dotnet stryker -m '!**/Codec.cs{1981..2175}'
→ 25 mutants fewer are tested; the span's mutants are gone from the report. Score changes accordingly.
Ran the comparison three times (including with path variants src/... and **/...): config route never applies the span, CLI route always does.
Other config keys (solution, target-framework, mutation-level, concurrency, reporters, additional-timeout) all take effect from the same config file, so the file itself is being read.
Expected behavior
- Span filters in the config
mutate array behave identically to CLI -m, or
- Stryker warns that a span filter could not be applied / is unsupported in config.
Silently ignoring an exclusion is the worst outcome: it inflates the mutation score denominator and can hide an over-restrictive exclude during review.
Note
This matters for teams that exclude proven-equivalent mutants via config (e.g. generated from an equivalent-mutants ledger). We now generate CLI args from a script instead — happy to share the approach.
Stryker.NET version: 4.16.0
OS: macOS 15 (arm64)
.NET SDK: 8.0.130
Test framework: xUnit 2.9.2 + Reqnroll (also reproduced with SpecFlow)
Summary
Span filters (
File.cs{start..end}) in themutatearray ofstryker-config.jsonare silently ignored. The exact same span passed via CLI-mworks correctly.Reproduction
Setup: a project under test with a line range (e.g. lines 61–64 of
Codec.cs) that should be excluded from mutation. Character offsets for that range are 1981–2175 (note: spans are character indices per the docs — that part works fine via CLI).Config route — NOT excluded:
stryker-config.json:{ "stryker-config": { "solution": "Wop.Sdk.sln", "target-framework": "net8.0", "mutation-level": "Advanced", "mutate": ["!src/Wop.Sdk/Codec.cs{1981..2175}"] } }Run:
dotnet stryker→ mutants inside the span are still created and tested (830 mutants tested;Codec.cslines 61–64 mutants present in mutation-report.json).CLI route — excluded correctly:
→ 25 mutants fewer are tested; the span's mutants are gone from the report. Score changes accordingly.
Ran the comparison three times (including with path variants
src/...and**/...): config route never applies the span, CLI route always does.Other config keys (
solution,target-framework,mutation-level,concurrency,reporters,additional-timeout) all take effect from the same config file, so the file itself is being read.Expected behavior
mutatearray behave identically to CLI-m, orSilently ignoring an exclusion is the worst outcome: it inflates the mutation score denominator and can hide an over-restrictive exclude during review.
Note
This matters for teams that exclude proven-equivalent mutants via config (e.g. generated from an equivalent-mutants ledger). We now generate CLI args from a script instead — happy to share the approach.