ADR 0010: Adopt PHPUnit 13 after retiring empty Codeception suites
- Status: accepted and implemented — PHPUnit 13.3.3 installed; isolated comparison and focused main-workspace QA verified
- Date: 2026-08-21
- Updated: 2026-09-13
Current decision — 2026-09-13
Adopt phpunit/phpunit ^13.3.3 and PHPUnit XML schema 13.3, preserving the
existing class-based tests. Remove Codeception and its empty Api and
Acceptance infrastructure. Keep justinrainbow/json-schema as an explicit
development dependency for Discovery's provider-schema test. Pest 5 remains
unselected; no syntax conversion or mixed-framework migration is introduced.
The owner explicitly authorized Codeception removal and evaluation of updated
PHPUnit 13. The completed comparison executes the same 630 classes / 3,094
cases / 20,702 assertions on PHPUnit 12.5.35 and 13.3.3, with zero errors,
four identical pre-existing failures and zero skips. Focused coverage
preserves every shared covered executable line; changes to structural match
line classification are documented. The configured PHPStan scope produces the
same 438 findings after path normalization.
Three sequential paired repetitions each pass 70 cases / 408 assertions. Median wall time changes from 47.387 to 47.678 seconds (+0.61%); maximum peak RSS changes from 263.51 to 265.54 MiB (+0.77%). No performance win is claimed.
The selected method explicitly differs from the original two-candidate
protocol: four disjoint class shards establish complete-inventory equivalence,
and a sequential representative sample measures timing and memory. This does
not prove the original single-process full-suite performance budgets or
cross-class ordering equivalence. Windows execution was not tested. The four
existing failures and diagnostics remain open; adoption does not make the
full suite green. Full evidence and failure classifications are maintained in
doc/public/en/quality/test-framework-direction.md.
The manifest and schema encode the decision, and the main workspace contains
the tested candidate dependency graph with no Codeception package or binary.
Focused composer qa:test verification passes 70 tests / 408 assertions and
produces fresh XML/JSON reports (reports/p9-main-qa.txt). The direct
integration alias passes one selected test / seven assertions
(reports/p9-main-integration-alias.txt); both commands complete despite a
one-second Composer process timeout. Composer audit reports no advisories;
strict validation retains only the same two baseline manifest warnings, with
no stale-lock warning. These checks do not turn the four existing full-inventory
failures into passes. This decision does not reopen deferred cleanup,
settings migration or signage work.
Original context
The original baseline used PHP 8.5, PHPUnit 12.5 and Codeception 5. A disposable Pest 4.7.8 probe ran seven existing PHPUnit-style tests successfully, but Pest 5 is now the current Pest major and uses PHPUnit 13. Treating the Pest 4 result as the migration target would optimize for a superseded generation and require a second major transition later.
PHPUnit 13 is also available and compatible with the project's PHP floor. A framework migration and a test-foundation upgrade must therefore be evaluated together rather than comparing Pest 4 with the current PHPUnit suite.
Original decision — 2026-08-21
The original adoption candidates were:
- a direct upgrade from PHPUnit 12.5 to PHPUnit 13; and
- a direct move to Pest 5 on its PHPUnit 13 foundation.
Pest 4 is not an adoption candidate. Its isolated probe is retained only as historical compatibility evidence and left no dependency or configuration in the repository.
The original direction alone did not authorize a dependency change. On
2026-09-13 the owner explicitly chose to remove Codeception and evaluate
updated PHPUnit 13. That decision supersedes the former owner gate and selects
the existing class-based suite for the isolated upgrade comparison; no Pest
conversion is requested. The adoption evidence belongs in
doc/public/en/quality/test-framework-direction.md.
Original consequences
- Documentation must continue to identify PHPUnit 12.5 as the actual committed baseline until an upgrade is implemented and verified.
- PHPUnit deprecations must be cleared before attempting PHPUnit 13.
- Pest 5 must first run representative existing PHPUnit-style tests before any syntax conversion is assessed.
- The final decision must compare equivalent assertions, coverage, runtime, diagnostics, static analysis, Codeception coexistence and cross-platform behavior.
- Test-stack work is scheduled after the active P3 sidebar increment and must not absorb deferred P4, P5, P6 or signage scope.
Historical outcome of the comparison — 2026-08-25
The original experiment ran. Its full evidence is in
doc/public/en/quality/test-framework-direction.md; these results describe
the August snapshot:
- PHPUnit deprecations are cleared. All 13 came from
isType(), removed in PHPUnit 13; the suite now reports zero on 12.5 with the assertion count unchanged. This ADR's precondition is satisfied. - PHPUnit 13.0.6 runs the suite with identical tests, errors, failures, notices, runtime and peak memory. There is no measured performance argument either way.
- Codeception 5.3.5 caps
phpunit/php-code-coverageat^13.0, which pins PHPUnit to 13.0.x and makes every Pest 5 release unresolvable. Pest 5 was therefore eliminated on dependency resolution, before any authoring comparison, and no sample conversion was performed. - The Codeception
ApiandAcceptancesuites contain no tests and never have. The constraint above is being paid for a gate that verifies nothing.
That result left a product question: keep, populate or remove Codeception. The owner answered it on 2026-09-13 by authorizing removal and evaluation of updated PHPUnit 13. The historical 13.0.x cap is no longer an adoption reason. Pest 5 stays unselected; re-evaluation is dated 2027-02-05, or earlier for a specific maintenance need with a reviewed representative conversion. No mixed authoring surface or indefinite migration is introduced.