Description
Problem
The current tests command only runs PHPUnit in a single process. For medium and large test suites, this increases execution time unnecessarily and makes local feedback loops and CI pipelines slower than they need to be.
At the same time, adding parallel execution in a naive way often introduces practical problems such as unstable coverage output, resource contention, or the need for test-suite-specific workarounds. The goal here is not to expose a parallel mode that works only in ideal cases, but to provide one that is safe, predictable, and usable in common real-world projects without forcing drastic changes to existing tests.
Proposal
Add a new option to the command:
dev-tools tests --parallel
Suggested behavior:
--parallel enables parallel execution transparently
- default behavior remains unchanged when the flag is absent
- the implementation should preserve the current command contract as much as possible
- coverage, filtering, bootstrap, config, and cache options should continue to work consistently in parallel mode
An optional extension could be:
dev-tools tests --parallel[=N]
Where:
--parallel uses an automatic worker count
--parallel=4 forces a specific number of workers
Implementation direction
The most practical default appears to be integrating ParaTest, whose stated goal is parallel execution for PHPUnit, with “zero configuration” for well-written PHPUnit suites, support for running across multiple processes, and combined code-coverage reporting. 
A possible strategy:
- keep
vendor/bin/phpunit as the default runner
- switch to
vendor/bin/paratest when --parallel is enabled
- preserve existing options by translating them to the parallel runner when compatible
- keep output and exit-code behavior aligned with the current command
Requirements
This feature should aim for the following guarantees:
- parallel mode MUST be opt-in
- enabling
--parallel MUST NOT require consumers to redesign their test suite
- the common case should work without custom bootstrap hacks, per-process shell scripts, or intrusive test rewrites
- code coverage should still be supported in a first-class way
- the implementation should avoid surprising behavior differences between serial and parallel execution
Non-goals
This issue is not requesting a “best effort” parallel mode that pushes complexity to the user. In particular, the solution should avoid requiring common consumers to:
- manually shard suites
- rewrite large portions of integration tests
- introduce custom process-token plumbing in application code
- maintain separate bootstrap files just to make parallel execution usable
Notes on common pitfalls
Parallel execution tools can expose contention when tests share mutable resources such as databases, filesystem state, or caches. ParaTest itself documents that these issues can occur in suites that are not isolated around shared resources. 
Because of that, this feature should be designed around safe defaults and a strong expectation that the command abstraction handles the common path cleanly. That may include implementation details such as:
- selecting a stable runner mode by default
- preserving PHPUnit configuration semantics
- handling coverage aggregation automatically
- documenting only minimal, non-invasive expectations around test isolation
Possible approaches
1. ParaTest-backed runner
Use ParaTest when --parallel is enabled. This is likely the best default because it is purpose-built for parallel PHPUnit execution and explicitly supports combined coverage output. 
2. Automatic worker-count strategy
Detect a sensible worker count automatically, with an override available through --parallel=N.
3. Conservative compatibility mode
If some PHPUnit arguments are not safe in a given parallel mode, the command should handle that internally rather than forcing the user to discover caveats by trial and error.
4. Optional future extension
A later enhancement could expose a more advanced mode for projects that want finer-grained scheduling, but the first implementation should optimize for zero-friction adoption.
Expected behavior
Example:
dev-tools tests --parallel
dev-tools tests --parallel=8 --filter=UserServiceTest
dev-tools tests --parallel --coverage=./tmp/coverage
Expected result:
- faster execution for most suites
- no behavioral regression when the flag is omitted
- no drastic test-code modifications required for ordinary adoption
- no extra workaround layer required just to make the flag usable
Benefits
- significantly faster local test feedback
- faster CI pipelines
- better developer experience
- adoption path that stays aligned with existing PHPUnit usage
- keeps the abstraction at the dev-tools tests level instead of making each consumer assemble its own parallel strategy
Additional Context
There are other ways to parallelize test execution, including distributing test workloads across CI jobs instead of parallelizing inside one process host, but that solves a different layer of the problem. This issue is specifically about adding local command-level parallel execution behind the existing tests command.
Description
Problem
The current tests command only runs PHPUnit in a single process. For medium and large test suites, this increases execution time unnecessarily and makes local feedback loops and CI pipelines slower than they need to be.
At the same time, adding parallel execution in a naive way often introduces practical problems such as unstable coverage output, resource contention, or the need for test-suite-specific workarounds. The goal here is not to expose a parallel mode that works only in ideal cases, but to provide one that is safe, predictable, and usable in common real-world projects without forcing drastic changes to existing tests.
Proposal
Add a new option to the command:
dev-tools tests --parallelSuggested behavior:
--parallelenables parallel execution transparentlyAn optional extension could be:
dev-tools tests --parallel[=N]Where:
--paralleluses an automatic worker count--parallel=4forces a specific number of workersImplementation direction
The most practical default appears to be integrating
ParaTest, whose stated goal is parallel execution for PHPUnit, with “zero configuration” for well-written PHPUnit suites, support for running across multiple processes, and combined code-coverage reporting. A possible strategy:
vendor/bin/phpunitas the default runnervendor/bin/paratestwhen--parallelis enabledRequirements
This feature should aim for the following guarantees:
--parallelMUST NOT require consumers to redesign their test suiteNon-goals
This issue is not requesting a “best effort” parallel mode that pushes complexity to the user. In particular, the solution should avoid requiring common consumers to:
Notes on common pitfalls
Parallel execution tools can expose contention when tests share mutable resources such as databases, filesystem state, or caches.
ParaTestitself documents that these issues can occur in suites that are not isolated around shared resources. Because of that, this feature should be designed around safe defaults and a strong expectation that the command abstraction handles the common path cleanly. That may include implementation details such as:
Possible approaches
1. ParaTest-backed runner
Use
ParaTestwhen--parallelis enabled. This is likely the best default because it is purpose-built for parallel PHPUnit execution and explicitly supports combined coverage output. 2. Automatic worker-count strategy
Detect a sensible worker count automatically, with an override available through
--parallel=N.3. Conservative compatibility mode
If some PHPUnit arguments are not safe in a given parallel mode, the command should handle that internally rather than forcing the user to discover caveats by trial and error.
4. Optional future extension
A later enhancement could expose a more advanced mode for projects that want finer-grained scheduling, but the first implementation should optimize for zero-friction adoption.
Expected behavior
Example:
Expected result:
Benefits
Additional Context
There are other ways to parallelize test execution, including distributing test workloads across CI jobs instead of parallelizing inside one process host, but that solves a different layer of the problem. This issue is specifically about adding local command-level parallel execution behind the existing tests command.