Closes #52: Make Unit/Integration bootstraps self-locating - #55
Conversation
|
Note Generated by the AI delivery pipeline (lead-reviewer · Claude Opus 4.8). Review: ✅ PASS Verified: Nice-to-haves:
|
|
Note Generated by the AI delivery pipeline (qa-engineer · Claude Opus 4.8). QA: Headless library (no UI) — Strategy B not applicable. Used API/Analysis (reading
Scope check: diff touches only Smoke tests:
Blockers:
|
PHPUnit re-runs the configured bootstrap file standalone in isolated
child processes (@runInSeparateProcess), where the wpmedia-phpunit bin
never runs and WPMEDIA_PHPUNIT_ROOT_DIR / WPMEDIA_PHPUNIT_ROOT_TEST_DIR
are never defined, causing a fatal. Guard both bootstraps to self-derive
the constants via BootstrapManager::setupConstants() when absent,
mirroring the bin's class_exists/require_once pattern, so consumers no
longer need a per-plugin Tests/{Unit,Integration}/init-tests.php shim
whose only job was to define these two constants.
Closes #52
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
13109c6 to
f87b243
Compare
Closes #52
Summary
PHPUnit re-runs the configured bootstrap file standalone in isolated child processes (
@runInSeparateProcess), where thewpmedia-phpunitbin never runs andWPMEDIA_PHPUNIT_ROOT_DIR/WPMEDIA_PHPUNIT_ROOT_TEST_DIRare never defined, causing a fatal "Undefined constant" error. This fix makes both bootstraps self-locating: they now guard-invokeBootstrapManager::setupConstants()at startup to self-derive the constants when absent, eliminating the need for consumers to maintain per-pluginTests/{Unit,Integration}/init-tests.phpshims whose only job was to pre-define these two constants.What was done
src/Unit/bootstrap.phpandsrc/Integration/bootstrap.php(before the existing requires).wpmedia-phpunitbin's pattern: guardedclass_exists()check,require_oncetheBootstrapManagerby relative path, then invokesetupConstants($suite).if ( ! defined() )) ensures idempotence: when the bin pre-defines the constants in the parent process, or when the package's own self-test pre-defines them viainit-tests.php, the block short-circuits and avoids a double-define warning (which becomes an exception underconvertWarningsToExceptions).How to test
composer test-unitandcomposer test-integrationboth remain green (119 and 29 tests respectively), confirming the guard short-circuits correctly andconvertWarningsToExceptionsdoes not trip.composer phpstanpasses against the existing baseline (no new issues introduced).@runInSeparateProcess): A consumer can now delete theirTests/{Unit,Integration}/init-tests.phpshims, point phpunit'sbootstrap=directly atvendor/wp-media/phpunit/src/Unit/bootstrap.php(or Integration), and run suites with isolated tests — the constants self-derive and no "Undefined constant" fatal occurs.Type of change
Affected Features & Quality Assurance Scope
Technical description
The root cause is architectural:
src/Unit/bootstrap.phpandsrc/Integration/bootstrap.phpuse the two constants but never define them — they assume a caller already did. This holds when invoked through thewpmedia-phpunitbin (which callsBootstrapManager::setupConstants()in the parent), but fails when PHPUnit re-executes the bootstrap file standalone in an isolated child process where the bin never ran.The fix is a root-cause repair, not a workaround: add the same guarded setup block to the bootstraps themselves. Since the autoloader is not yet registered at the top of the bootstrap (it is only required later in
init_test_suite()), we mirror the bin's approach: guard withclass_exists(), thenrequire_oncetheBootstrapManagerby relative path (dirname(__DIR__)→src/), then callsetupConstants($suite). Theif ( ! defined() )guard is load-bearing for the package's own self-test, which usesconvertWarningsToExceptions="true"and pre-defines the constants viaTests/{Unit,Integration}/init-tests.php— a re-define()would emit a warning and become a fatal.The derivation itself is unchanged:
BootstrapManager::getRootDir(false)walks four levels up fromsrc/to the consumer root (verified against the existinggetRootDir.phptest case), andsetupConstants()defaults the test directory toWPMEDIA_PHPUNIT_ROOT_DIR . '/Tests/' . ucfirst($suite)when nopath=override is present (the isolated-child case, where argv carries only PHPUnit's own args).New dependencies
None.
Risks
None identified. The fix is guarded and mirrors the well-tested bin pattern; it only adds logic to an already-defined block in both bootstraps.
Notes
Intentional scope exclusions:
Tests/{Unit,Integration}/init-tests.phpare not deleted. They must stay: the package is not installed undervendor/, sogetRootDir(false)'s four-levels-up walk would resolve outside the repo and break the self-test (the documented "self-test caveat" in CLAUDE.md).wpmedia-phpunitbin is unchanged.WPMEDIA_PHPUNIT_SRCenv var or composerextraconfig to scope code-coverage) is a separate concern and deferred as a potential follow-up (Improve the library to include classes that could be common to all plugins. #30 scope). It is not trivially coupled to this deliverable.Contributes to #30 (reduce per-plugin boilerplate).