Detecta test lentos en PHPUnit

Los test en tus pruebas automatizadas tienen que ser rápidos. Muy rápidos. Si tus test tardan mucho al final dejarán de usarse. Para hacerte una idea, un test lento es aquel que supere los 500 milisegundos.

PHPUnit Speedtrap

Si trabajas con PHPUnit puedes detectar los test lentos usando PHPUnit Speedtrap. Es una herramienta que identificará los que superen un determinado tiempo de ejecución. Si no indicamos nada se considerará lento aquel que supere los 500 ms.

Es muy útil cuando sospechas de algún test lento. Yo la uso ya en todos mis proyectos.

Instalación

Podemos instalarlo desde la línea de comandos:

composer require --dev johnkary/phpunit-speedtrap

O también podemos modificar directamente el fichero composer.json añadiendo el paquete en la sección require-dev:

    "require-dev": {
        "johnkary/phpunit-speedtrap": "^3.2"
    },

Y después ejecutando el comando:

composer install

Configuración de PHPUnit Speedtrap

Para usar este paquete de PHPUnit tenemos que añadir (si no existe) la sección listeners como se indica a continuación:

<phpunit bootstrap="vendor/autoload.php" colors="true">

    <testsuites>
        <testsuite name="app">
            <directory>tests</directory>
        </testsuite>
    </testsuites>

    <listeners>
        <listener class="JohnKary\PHPUnit\Listener\SpeedTrapListener">
            <arguments>
                <array>
                    <element key="slowThreshold">
                        <integer>500</integer>
                    </element>
                    <element key="reportLength">
                        <integer>5</integer>
                    </element>
                </array>
            </arguments>
        </listener>
    </listeners>
</phpunit>

El elemento slowThreshold indica el límite en milisegundos a partir del cual un test se considera lento. En este caso hemos puesto 500 milisegundos.

El elemento reportLength indica el número de test que se van a mostrar en los resultados. El valor por defecto es 10. Yo suelo dejarlo en 5 porque intento corregir los tests lentos según van apareciendo.

Un test lento de prueba

Ya tenemos todo listo así que vamos a probar que funciona correctamente. Vamos a crear un test absurdo para ver cómo lo detecta. Un test absurdo que se me ocurre puede ser:

/** @test */
public function test_lento()
{
    sleep(1);

    $this->assertEquals(1, 1);
}

Al lanzar phpunit vemos que, como esperábamos, nos ha detectado un test lento:

$ vendor/phpunit/phpunit/phpunit
 PHPUnit 9.0.1 by Sebastian Bergmann and contributors.
 …..                                                               5 / 5 (100%)
 You should really speed up these slow tests (>500ms)…
 1000ms to run PruebaTest:test_lento 
 Time: 1.05 seconds, Memory: 4.00 MB
 OK (1 tests, 1 assertions)

¿Y si algún test TIENE que ser más lento?

Hay ocasiones (muy pocas) en las que un test tiene que ser muy lento. Insisto, muy pocas ocasiones.

Si realmente hay un test que deba ser lento tenemos la opción de darle un límite diferente al que hemos definido. Para eso en la definición del test incluimos el parámetro @slowThreshold:

/** @test
 *  @slowThreshold 1100
 */
public function test_lento()
{
    sleep(1);

    $this->assertEquals(1, 1);
}

Me siento solo, dime algo...