facile-it/paraunit
Run PHPUnit test suites faster by executing tests in parallel across multiple processes. Symfony-based CLI with Composer install, supports many PHPUnit/Symfony versions, and can collect code coverage in parallel (auto-picks best driver like PCOV/Xdebug).
Installation:
composer require --dev facile-it/paraunit
Ensure your phpunit.xml includes the Paraunit bootstrap extension (added automatically on first run if missing).
First Run:
vendor/bin/paraunit run
This executes all tests in parallel using multiple PHPUnit processes.
Coverage:
vendor/bin/paraunit coverage --html=./coverage
Automatically detects and uses the fastest coverage driver (Pcov/Xdebug/PHPDbg).
--debug to see full process output.Replace phpunit in CI:
# .github/workflows/tests.yml
- run: vendor/bin/paraunit run --stop-on-failure
Use --stop-on-* flags to mirror PHPUnit’s behavior (e.g., --stop-on-failure).
Chunked Execution:
vendor/bin/paraunit run --chunk-size=50
Split tests into chunks of 50 classes for better resource management.
Exclude Test Suites:
vendor/bin/paraunit run --exclude-testsuite="Integration"
Skip specific suites (e.g., slow integration tests).
Randomized Order:
vendor/bin/paraunit run --sort=random
Mitigate test dependencies by shuffling execution order.
Database Transactions:
Paraunit runs tests in parallel, so ensure your DatabaseTransactionsTrait or RefreshDatabase uses isolated connections (e.g., SQLite in-memory or PostgreSQL with DB_CONNECTION=pgsql_parallel in .env).
Service Container Isolation:
Use FreshServices or FreshOnEachTest in Laravel’s TestCase to avoid shared state:
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\Concerns\InteractsWithContainer;
class TestCase extends \Tests\TestCase {
use RefreshDatabase, InteractsWithContainer;
}
Artisan Commands: Mock or stub Artisan commands in tests to avoid race conditions:
$this->artisan('command')->expectsOutput('...')->assertExitCode(0);
Pass-Through Options: Forward PHPUnit flags directly:
vendor/bin/paraunit run -- --filter="testMethod"
Use --pass-through to bypass Paraunit’s parsing.
Coverage Cache: Warm up coverage cache for faster runs:
vendor/bin/paraunit coverage --coverage-cache-warmup
Database Deadlocks:
DB::connection('pgsql_parallel')->getPdo() with pg_prepare or switch to SQLite for tests.Stateful Tests:
config(), app(), or static state will interfere.FreshServices.Coverage Gaps:
--coverage-clover=coverage.clover).PHPUnit Configuration:
displayDetailsOnTestsThatTriggerDeprecations by default.phpunit.xml:
<php>
<displayDetailsOnTestsThatTriggerDeprecations>true</displayDetailsOnTestsThatTriggerDeprecations>
</php>
Debug Mode:
vendor/bin/paraunit run --debug
Shows full process output for failed tests.
Log Analysis:
Check paraunit.log in your project root for parallelization errors.
Transient Dependencies:
Use --transient-dependencies to handle flaky external services (e.g., APIs):
vendor/bin/paraunit run --transient-dependencies="HttpClient"
Custom Bootstrap:
Extend Paraunit’s bootstrap logic by overriding the Paraunit\Bootstrap class or using PHPUnit’s setUp()/tearDown().
Parallel Hooks:
Implement Paraunit\Event\ParallelTestListener to hook into test execution phases (e.g., pre/post-test callbacks).
Coverage Drivers:
Add custom drivers by extending Paraunit\Coverage\Driver\AbstractDriver.
PHPUnit 13+:
Paraunit 2.8+ supports PHPUnit 13’s deprecation reporting. Ensure your phpunit.xml includes:
<php>
<errorReporting>E_ALL</errorReporting>
</php>
Symfony 8+: Paraunit 2.7.1+ drops Symfony 7 support. For Symfony 8, use:
vendor/bin/paraunit run --symfony=8
Windows Compatibility:
Paraunit relies on pcntl for parallelism. Use WSL or Docker for Windows setups.
Optimal Chunk Size:
Start with --chunk-size=30 for medium test suites; adjust based on CI resource limits.
Memory Limits:
Increase PHP memory (-d memory_limit=1G) if tests hit limits during parallel runs.
Exclusion Patterns:
Skip slow tests with --exclude-group="slow" (requires PHPUnit’s @group annotations).
How can I help you explore Laravel packages today?