Motivation
Two gaps in the current testing story:
- Ext/DB-backed tests are CI-only. Tests that need
ext-mongodb, ext-redis, ext-memcached, Beanstalk (pda/pheanstalk), or a live database for the Cycle ORM bridge (univeros/persistence) cannot run on a typical dev machine without those extensions/services installed, so they only really execute in CI. That makes a whole class of integration code slow to iterate on and easy to break locally without noticing (e.g. the MongoSessionHandlerTest tearDown() quirk).
- Suite wall-clock grows. As packages land (the suite is already 200+ tests across 28 packages) a single-process PHPUnit run gets slower, especially once container-backed integration tests are added.
These two tools are complementary and address both:
- testcontainers-php — spin up throwaway Docker containers (Mongo, Redis, Memcached, Beanstalk, MySQL/Postgres) per test run, so the ext/DB integration tests run identically locally and in CI, with no global service install.
- paratest — parallelize the PHPUnit 11 suite to keep it fast as it grows.
Proposed scope
Risks / open questions
- Isolation under parallelism is the crux. paratest runs N worker processes; if they share one Redis/DB container they will contaminate each other. Options: a container instance per worker (
TEST_TOKEN-keyed), or one container with per-test isolation (unique DB name / Redis keyspace / Mongo database per test). Needs a decision before porting tests.
- Docker becomes a dev/CI prerequisite for the integration suite. The unit suite must stay Docker-free and fast (graceful skip when Docker is absent).
- Coverage + paratest + the TestReporter extension interaction needs verifying (merging per-process coverage; the golden-file determinism of
build/test-results.json).
- Container boot time vs. CI minutes — measure before/after.
Related
- Pairs naturally with
univeros/doctor's database_reachable / extensions_loaded checks — a container-backed dev loop makes those probes pass locally instead of skipping.
- Separate initiative from the introspection/suggest tooling; this is purely test infrastructure.
Motivation
Two gaps in the current testing story:
ext-mongodb,ext-redis,ext-memcached, Beanstalk (pda/pheanstalk), or a live database for the Cycle ORM bridge (univeros/persistence) cannot run on a typical dev machine without those extensions/services installed, so they only really execute in CI. That makes a whole class of integration code slow to iterate on and easy to break locally without noticing (e.g. theMongoSessionHandlerTesttearDown()quirk).These two tools are complementary and address both:
Proposed scope
brianium/paratest(dev) and wire acomposer test:parscript alongside the existingcomposer test. Confirm it cooperates with theAltair\TestReporterPHPUnit extension (JSON report) and coverage.TestCase/trait that lazily boots the container a given integration test needs, skipping gracefully when Docker is unavailable (socomposer testwithout Docker still works, like today)..github/workflows/ci.yml) to use the container-backed path and (optionally) paratest, removing the bespoke service setup.Risks / open questions
TEST_TOKEN-keyed), or one container with per-test isolation (unique DB name / Redis keyspace / Mongo database per test). Needs a decision before porting tests.build/test-results.json).Related
univeros/doctor'sdatabase_reachable/extensions_loadedchecks — a container-backed dev loop makes those probes pass locally instead of skipping.