fix(infection): skip mutations to #[TestInline] attribute arguments (#159) - #261
fix(infection): skip mutations to #[TestInline] attribute arguments (#159)#261rossaddison wants to merge 3 commits into
Conversation
…hp-testo#159) When Infection mutates values inside a #[TestInline(arguments: [...], result: ...)] attribute it is mutating test data, not production logic. Every such mutation is "killed" (Assert::same catches the wrong expected value), but the kills are semantically meaningless — they verify that the assertion works, not that the source code handles a mutation correctly. This inflates the mutation score with noise and wastes CI runner time. Add `global-ignoreSourceCodeByRegex` to infection.json so Infection skips any mutation whose source line contains `#[TestInline`. This covers all single-line attribute declarations in both the Self-test fixtures under plugin/inline/tests/Self/ and any production code that uses the attribute. Method bodies on adjacent lines are unaffected and continue to be mutated. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
SummaryWhat the fix does: adds One line change to one config file. |
…is mirrored tests/Application/Stub/EmptyRun/ is intentionally empty — it is the test fixture for EmptyRunTest, which asserts that a Testo run over an empty directory yields Status::Risky with zero tests collected. Git does not track empty directories, and bin/build-phpunit.php only copies *.php files when populating the tests/PhpUnit/ mirror, so the mirror never contained tests/PhpUnit/Application/Stub/EmptyRun/. The mirrored EmptyRunTest resolved __DIR__ . '/../../Stub/EmptyRun' to that missing path and threw InvalidArgumentException: File or directory not found — aborting Infection's initial PHPUnit test run on every CI push to 1.x. Add .placeholder.php (no namespace, no classes, no tests) to the source directory. The build script copies it verbatim into the mirror, which creates the required directory. Testo's FinderConfig still discovers zero tests there, so Status::Risky is reported and the assertion holds. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
…urceCodeByRegex
Specifying "mutators": {} without "@default" treats the block as an
allowlist, so all default mutators were silently disabled — producing
0 mutations and an MSI failure. Adding "@default": true restores the
full default mutator set while the global regex filter still skips
lines containing #[TestInline.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Fix: 0 mutations generated → MSI failureRoot causeAdding a What happenedThe original "mutators": {
"global-ignoreSourceCodeByRegex": ["#\[TestInline"]
}
FixAdd "mutators": {
"@default": true,
"global-ignoreSourceCodeByRegex": ["#\[TestInline"]
}Also included in this branch
|
|
We discussed the issue there infection/infection#3053 (comment) |
Problem
When Infection mutates values inside a
#[TestInline(arguments: [...], result: ...)]attribute it is mutating test data, not production logic.Every such mutation is "killed" —
Assert::samecatches the changed expected value — but the kills are semantically meaningless: they verify that the assertion mechanism works, not that the source code handles a production code mutation correctly. This inflates the mutation score with noise and wastes CI runner time.Concrete example in
plugin/inline/tests/Self/StaticMethods.php:When
result: 2is changed toresult: 3,Assert::same(2, 3)fails — the mutant is "killed", but no useful information was gained about the production code.Fix
Add
global-ignoreSourceCodeByRegextoinfection.json:Infection skips any mutation whose source line contains
#[TestInline. This covers:#[TestInline(...)]attribute lines inplugin/inline/tests/Self/fixturesMethod bodies on adjacent lines are unaffected and continue to be mutated normally — so regressions in
publicSum,privateMul, etc. are still caught.Verification
All 23 inline plugin tests pass unchanged. The fix is a pure config addition with no code changes.
Fixes #159