ergebnis/phpunit-slow-test-detector
Detect slow PHPUnit tests with an extension delivered as a Composer package or PHAR. Configure a global maximum duration and get a report of tests exceeding the threshold after each run—ideal for catching performance regressions in your suite.
composer require --dev ergebnis/phpunit-slow-test-detector
phpunit.xml:
Add the extension to your PHPUnit config based on your PHPUnit version (see README for version-specific instructions).
Example for PHPUnit 10+:
<phpunit ...>
<extensions>
<bootstrap class="Ergebnis\PHPUnit\SlowTestDetector\Extension"/>
</extensions>
</phpunit>
./vendor/bin/phpunit
The extension will now report slow tests (default threshold: 500ms).Run your test suite and observe the output. The extension lists tests exceeding the default maximum-duration (500ms) in a table format. Example:
Detected 3 tests where the duration exceeded the global maximum duration (0.500).
# Duration Test
1 0.800 App\Tests\Feature\SlowApiTest::testLongRunningEndpoint
2 0.650 App\Tests\Unit\DatabaseSeederTest::testLargeDatasetLoad
3 0.550 App\Tests\Integration\PaymentGatewayTest::testRetryLogic
phpunit.xml: Place the extension config in phpunit.xml (located in the project root or tests/).maximum-duration parameter to set stricter thresholds for specific suites:
<phpunit>
<extensions>
<bootstrap class="Ergebnis\PHPUnit\SlowTestDetector\Extension"/>
</extensions>
<parameters>
<parameter name="maximum-duration" value="200" type="int"/>
</parameters>
<testsuites>
<testsuite name="unit">
<directory>tests/Unit</directory>
<parameter name="maximum-duration" value="100" type="int"/>
</testsuite>
</testsuites>
</phpunit>
--exit-code flag:
./vendor/bin/phpunit --exit-code 1
.env to set thresholds dynamically:
<parameter name="maximum-duration" value="{env('TEST_SLOW_THRESHOLD')}" type="int"/>
In .env:
TEST_SLOW_THRESHOLD=300 # 300ms
# Local (verbose)
./vendor/bin/phpunit --configuration phpunit.local.xml
# CI (strict)
./vendor/bin/phpunit --configuration phpunit.ci.xml
Extension class:
namespace App\Tests\Extensions;
use Ergebnis\PHPUnit\SlowTestDetector\Extension as BaseExtension;
class CustomSlowTestDetector extends BaseExtension
{
public function report(Report $report)
{
// Custom logic (e.g., Slack notifications)
parent::report($report);
}
}
Update phpunit.xml:
<extensions>
<bootstrap class="App\Tests\Extensions\CustomSlowTestDetector"/>
</extensions>
phpunit.xml):
<php>
<server name="XDEBUG_MODE" value="off"/>
</php>
docker-compose run --rm -e TEST_SLOW_THRESHOLD=1000 tests ./vendor/bin/phpunit
Version Mismatches:
bootstrap instead of extension).phpunit.xml.False Positives:
@group and filter in phpunit.xml:
<testsuites>
<testsuite name="fast">
<directory>tests/Unit</directory>
<exclude>@slow</exclude>
</testsuite>
</testsuites>
Performance Overhead:
maximum-duration=10000) may hide performance issues.Silent Failures:
SlowTestDetector: Initialized with max duration=500ms
--debug:
./vendor/bin/phpunit --debug
Configuration Errors:
maximum-duration values (e.g., strings) will be ignored. Use type="int" in phpunit.xml:
<parameter name="maximum-duration" value="500" type="int"/>
CI-Specific Thresholds:
<!-- phpunit.ci.xml -->
<parameter name="maximum-duration" value="200" type="int"/>
Visual Feedback:
--colors for better visibility:
./vendor/bin/phpunit --colors=always
Exclude Flaky Tests:
<extensions>
<bootstrap class="Ergebnis\PHPUnit\SlowTestDetector\Extension">
<parameter name="exclude" value="App\Tests\FlakyTest"/>
</bootstrap>
</extensions>
Laravel Artisan Alias:
// app/Console/Commands/TestSlow.php
namespace App\Console\Commands;
use Illuminate\Console\Command;
class TestSlow extends Command
{
protected $signature = 'test:slow';
protected $description = 'Run tests with slow test detection';
public function handle()
{
$this->call('phpunit', ['--configuration' => 'phpunit.xml']);
}
}
php artisan test:slow
GitHub Actions Integration:
- name: Run tests
run: ./vendor/bin/phpunit --exit-code 1
How can I help you explore Laravel packages today?