Appearance
date: 2026-06-08 tags: [mutation, infection, pest, dead-end, ci] status: active graduated_to:
Infection dropped its Pest adapter — a full migration off pest --mutate is a dead end
Symptom — evaluating a CI-cost handover that assumed Infection, a spike to migrate mutation testing from Pest's --mutate to Infection failed on this stack (Pest 4 / PHPUnit 12 / PHP 8.5), even after correcting an initial misconfiguration.
Root cause — Infection has no Pest adapter. It added a dedicated PestAdapter in 0.23.0 (2021, PR #1516, closing issue #1476) but has since removed it: no PestAdapter class exists in the latest stable (0.33.2, May 2024) or dev-master, and the config schema's testFramework enum is phpunit / phpspec / codeception / testo only. The remaining phpunit-adapter fallback breaks on Pest 4 / PHPUnit 12 two ways:
- Infection's
InitialConfigBuilderinjects a legacy PHPUnit-9<filter><whitelist>element; PHPUnit 12 validates strictly and Pest exits 1 even with every test green → Infection's initial-test gate aborts. (PR #1294 only suppresses this when a<coverage>block exists — ourphpunit.xmluses the newer<source>element, so the guard never fires.) - Pest records executing test classes as
P\Tests\…in coverage butTests\…in junit, so Infection can't map coverage→tests (Could not find any information for the test).
The PHPUnit-12 fixes that do exist (#2440 → PR #3043, Apr 2026) are unreleased and target the phpunit adapter, not Pest. Forcing it via --skip-initial-tests + external coverage hits break #2 and risks false-green mutants (escaped reported as killed).
Fix — none attempted; the migration was rejected. Stay on Pest's native pest --mutate. The real speed win (multi-core parallelism) comes from a self-hosted runner, not a different engine.
Guard — this signpost + CLAUDE.md's Mutation Testing Policy, which mandates pest --mutate. Re-open only if pestphp/pest#4 or infection#1521 ships a maintained Pest adapter.