test-05 reproduction
Public source retained with the related article. Generated results, dependency directories, runtime storage, secrets, and oversized binary artifacts are intentionally excluded.
README
# TEST-05 mutation-survivor experiment
This fixture supports the planned article *A Surviving Mutant Is a Question,
Not a Score*. It asks whether two green PHPUnit suites distinguish two selected
changes to a synthetic catalogue response translator.
The `Throw_` mutation removes the caller-visible missing-product exception.
The `EqualIdentical` mutation changes a loose comparison between two integers
to a strict comparison. The first is a meaningful defect. The second preserves
behavior for every value admitted by the method's typed status parameter.
## Run it
Docker is the only host dependency.
```sh
./run.sh
```
The runner builds digest-pinned PHP and Composer images, runs both ordinary
test suites, runs Infection with one worker, and retains each command, exit
code, duration, console output, mutation diff, summary, and JSON report under
`results/`. It returns non-zero unless the complete matrix is reproduced.
## Predeclared scope and budget
The experiment mutates only `src/CatalogueResponseTranslator.php` with exactly
`Throw_` and `EqualIdentical`. Infection runs with one worker and
`--with-uncovered` so the weak suite's missing exception path remains visible.
Each Infection command must finish within 2,000 milliseconds. The duration is
measured around a disposable container invocation after the image has been
built. It therefore includes container startup but excludes the image build
and dependency installation. This is an evidence gate for this tiny fixture,
not a recommended project or CI budget.
Both mutation commands deliberately require 100% MSI and Covered Code MSI.
Their expected exit code is `1`: the weak suite scores 0%, and the strong suite
scores 50% because the equivalent comparison mutant remains. The threshold is
a controlled demonstration, not a policy recommendation.
## Expected matrix
| Suite | Ordinary tests | `Throw_` | `EqualIdentical` | MSI |
| --- | --- | --- | --- | ---: |
| Weak: known product only | pass | not covered | escaped | 0% |
| Strong: known and missing products | pass | killed | escaped | 50% |
The machine-readable comparison also requires zero errors, syntax errors,
timeouts, skips, and ignores. It verifies that both suites evaluated the same
strict-comparison mutation and that the throw-removal mutant moved from not
covered to killed.
## Interpretation boundary
Infection determines whether a generated mutant was killed, escaped, not
covered, errored, or timed out. It cannot decide whether an escaped mutant
represents a missing requirement or equivalent behavior. That classification
comes from the valid input domain, the generated diff, and the behavior callers
actually need.
The fixture does not claim that two mutators represent a complete fault model,
that 100% MSI is desirable, or that its runtime generalizes to a Laravel
application. A database, queue, HTTP, or deployment defect needs evidence at
the boundary where that mechanism exists.
Retained files
- .dockerignore
- compare.php
- composer.json
- composer.lock
- Dockerfile
- infection-strong.json5
- infection-weak.json5
- README.md
- run.sh
- src/CatalogueResponseTranslator.php
- src/ProductNotFound.php
- suites/strong/phpunit.xml
- suites/weak/phpunit.xml
- tests/Strong/CatalogueResponseTranslatorTest.php
- tests/Weak/CatalogueResponseTranslatorTest.php