LongRunning PHPUnit Extension

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>