Introduction

Les tests unitaires sont exécutés très souvent. Il est important que le temps d’exécution soit très court pour deux raisons :

  • Avoir le retour sur leurs status le plus rapidement possible
  • Ne pas dissuader les développeurs de les lancer (même si la plateforme d’intégration est le garde-fou des tests automatisés)

Cependant, avec le temps, ces tests sont souvent de plus en plus lents à s’exécuter. Parfois, ce temps augmente significativement suite à l’ajout de nouveaux tests ou de nouvelles fonctionnalités. Et il n’est pas toujours facile d’identifier quel test monopolise ce temps de traitement.

Afin de mettre en exergue les tests les plus longs, John Kary a publié un article expliquant comment trouver les tests les plus lents. Sa solution se présente sous la forme d’un plugin pour phpunit : SpeedTrap.

Installation

Il est possible d’installer ce plugin avec composer de deux façons.

La première se réduit à la ligne de commande suivante :

$ composer require --dev johnkary/phpunit-speedtrap

La seconde méthode consiste à passer par le fichier composer.json en y ajoutant la section ci-dessous :

{
	"require-dev" : {
		"johnkary/phpunit-speedtrap" : "@dev"
	}
}

Puis, de mettre à jour les dépendances avec cette commande :

$ composer update

Configuration

Une fois le plugin installé, il faut configurer phpunit pour l’utiliser. Cette configuration se fait via le fichier phpunit.xml en déclarant le listener de SpeedTrap de cette façon :

<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="tests/bootstrap.php">
  <listeners>
        <listener class="JohnKary\PHPUnit\Listener\SpeedTrapListener" />
    </listeners>
</phpunit>

Par défaut, le plugin retourne les 10 tests les plus lents et qui prennent plus de 500ms. Bien évidemment, il est possible de modifier ses seuils en spécifiant des arguments au listener comme ci-dessous :

<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="tests/bootstrap.php">
  <listeners>
        <listener class="JohnKary\PHPUnit\Listener\SpeedTrapListener">
            <arguments>
                <array>
                    <element key="slowThreshold">
                        <integer>500</integer>
                    </element>
                    <element key="reportLength">
                        <integer>10</integer>
                    </element>
                </array>
            </arguments>
        </listener>
    </listeners>
</phpunit>

Utilisation

L’utilisation de SpeedTrap est très simple puisque qu’il suffit de lancer phpunit comme d’habitude :

$ phpunit
PHPUnit 4.7.7 by Sebastian Bergmann and contributors.

...............................................................  63 / 504 ( 12%)
............................................................... 126 / 504 ( 25%)
............................................................... 189 / 504 ( 37%)
............................................................... 252 / 504 ( 50%)
............................................................... 315 / 504 ( 62%)
............................................................... 378 / 504 ( 75%)
............................................................... 441 / 504 ( 87%)
............................................................... 504 / 504 (100%)


You should really fix these slow tests (>500ms)...
 1. 31459ms to run MyProject\OpenIdTest:testCheckStatusCode
 2. 1018ms to run MyProject\MyService\ProcessFileTest:testReadLines
 3. 924ms to run MyProject\MyService\ProcessFileTest:testLoadLinesOk
 4. 702ms to run MyProject\OpenIdTest:testLoadConfig
 5. 682ms to run MyProject\OpenIdTest:testLoadKeys
 6. 656ms to run MyProject\MyService\ProcessFileTest:testLoadLinesWithJson
 7. 647ms to run MyProject\MyService\ProcessFileTest:testApplyRules
 8. 533ms to run MyProject\AwsS3Test:testCreateNewBucket


Time: 40.47 seconds, Memory: 62.50Mb

OK (504 tests, 1211 assertions)

Le compte-rendu de SpeedTrap s’affiche dans la console après l’exécution des tests et avant le compte-rendu des tests. Dans l’exemple ci-dessus, 8 tests prennent plus de 500ms. L’un d’entre-eux met près de 32s sur un temps total de 40s ! Un bon axe d’optimisation, non ? 🙂 De plus, il concerne un test sur de l’OpenID Connect. Il y a de fortes chances pour que ce test fasse appel à un serveur distant et ne soit donc pas un test unitaire mais un test d’intégration…

Conclusion

SpeedTrap est non-intrusif et permet d’identifier très simplement et très rapidement les tests les plus lents. Il se révèle être un bon outil pour maintenir une bonne fluidité dans le processus de développement et donc pour s’assurer que la productivité des développeurs ne se dégrade pas.