I was running a test suite and noticed that a couple of the tests were stalling. I didn't know which were running slow, so I investigated how I can log which tasks were taking too long to run.
After a quick search, I found two useful articles. David Llop wrote an article Identifying the slowest tests in PHPUnit about logging test times to a database that can be queried. However, Finding Slow Tests in PHPUnit 9 written by Aaron Saray was what I was looking for. He mentioned that some tweaks need to be made for it work with Laravel, so I decided to give it a go. Here is what I came up with;
The Extension
I used Aaron’s base code and extended it slightly. I made the seconds configurable and set up the Laravel $migrated
state as he mentioned. I also moved the file to an extensions
folder, to keep it organised. Now the class looks like this;
<?php
namespace Tests\Extension;
use Illuminate\Foundation\Testing\RefreshDatabaseState;
use PHPUnit\Runner\AfterTestHook;
use PHPUnit\Runner\BeforeTestHook;
class LongRunning implements AfterTestHook, BeforeTestHook
{
protected bool $migrating = false;
public function __construct(protected int $maxSeconds = 10)
{
}
public function executeBeforeTest(string $test): void
{
if (! RefreshDatabaseState::$migrated) {
$this->migrating = true;
}
}
public function executeAfterTest(string $test, float $time): void
{
if (! $this->migrating && $time > $this->maxSeconds) {
$stream = fopen('php://stderr', 'w')
fwrite($stream, sprintf("\nThe %s test took %s seconds.\n", $test, $time));
}
}
}
You can configure the $maxSeconds
in the PHPUnit XML configuration file like this;
<extensions>
<extension class="Tests\Extension\LongRunning">
<arguments>
<integer>10</integer>
</arguments>
</extension>
</extensions>