phork is a runtime-based parallel test distribution tool for PHPUnit. It intelligently distributes your test files across multiple workers using previous execution time data, minimising total CI time through load-balanced parallel runs.
- Runtime-aware distribution – parses JUnit XML logs to balance test load by actual execution time
- Graceful fallback – uses round-robin distribution when no prior runtime data is available
- Merged JUnit output – combines per-worker JUnit XML reports into a single file
- Auto CPU detection – automatically picks the number of workers based on available CPU cores
- PSR-4 aware – reads simple PSR-4 mappings in
composer.json(one directory per namespace) to map file paths to PHP class names
composer require --dev kaz29/phork# Run tests in parallel across all available CPU cores
./vendor/bin/phork --test-dir=tests/First, generate a JUnit baseline with a regular PHPUnit run:
vendor/bin/phpunit --log-junit junit.xmlThen use that baseline to balance the next run:
./vendor/bin/phork --workers=4 --log=junit.xml --test-dir=tests/ --output=results.xml| Option | Default | Description |
|---|---|---|
--workers=N |
auto (CPU cores) | Number of parallel worker processes |
--log=PATH |
(none) | Path to a previous JUnit XML file used for runtime-based distribution |
--test-dir=PATH |
tests/ |
Directory to scan for *Test.php files |
--output=PATH |
same as --log |
Path to write the merged JUnit XML result |
Note: If you specify
--logbut omit--output, the merged result will overwrite your baseline JUnit file. It is recommended to always set--outputexplicitly.
- Scan – recursively discovers all
*Test.phpfiles under--test-dir - Parse – reads
--log(if provided) to build a class → execution-time map - Split – distributes test files into
--workersbuckets using a greedy load-balancing algorithm (falls back to round-robin with no prior data) - Run – spawns one
paratestprocess per bucket in parallel - Merge – combines JUnit XML results from all workers into
--output
The repository ships Dockerfiles for PHP 8.3 and 8.4 and a compose.yml for local development:
# Start services (PHP 8.4 + PostgreSQL)
docker compose up -d
# Run tests inside the container
docker compose exec phork-app vendor/bin/phpunit# Install dependencies
composer install
# Run unit tests
vendor/bin/phpunit --testsuite Unit
# Run integration tests
vendor/bin/phpunit --testsuite IntegrationWhen running tests in parallel, each worker needs its own database. Use the TEST_TOKEN environment variable provided by paratest in your bootstrap.php:
// tests/bootstrap.php
$token = getenv('TEST_TOKEN') ?: '1';
putenv("DB_DATABASE=testdb_{$token}");This project is licensed under the MIT License.