Exécuter des assertions Blackfire dans atoum
Introduction
Depuis la sortie de sa version 2, Blackfire permet d’automatiser les tests de performance.
Cela passe par un SDK PHP qui permet, entre autres, d’intégrer des tests de performance dans PHPUnit : il est par exemple possible de vérifier qu’une portion de code ne dépasse pas une certaine limite de mémoire utilisée, un certain temps d’éxécution ou un certain nombre d’appels d’une fonction/méthode.
Comment peut-on intégrer ces tests dans le framework de tests unitaires atoum et ainsi bénéficier de la facilité d’utilisation de ses asserters ?
Installation
Blackfire aura préalablement été installé, ainsi qu’atoum.
Nous allons tout d’abord récupérer l’extension Blackfire pour atoum via composer.
composer require atoum/blackfire-extension
Il faut ensuite la configurer avec nos client id et client token pour accéder à Blackfire, en rajoutant quelques lignes dans le fichier .atoum.php
. Par exemple, ici en les récupérant depuis les variables d’environnement :
$extension = new mageekguy\atoum\blackfire\extension();
$extension
->setClientConfiguration(new \Blackfire\ClientConfiguration($_ENV['BLACKFIRE_CLIENT_ID'], $_ENV['BLACKFIRE_CLIENT_TOKEN']))
->addToRunner($runner)
;
Utilisation
L’extension va nous rajouter un nouvel asserter : blackfire
.
Sur celui-ci, il sera possible d’appeler ces méthodes :
- assert
- defineMetric
- profile
Prenons donc cet exemple de test :
<?php
namespace Tests\Units;
use Example as TestedClass;
use atoum;
class Example extends atoum
{
public function testExemple()
{
$this
->blackfire
->assert('main.wall_time < 2s')
->profile(function() {
sleep(4);
// appeler le code testé.
})
;
}
}
Ce test va vérifier que le code appelé dans la fonction anonyme ne prends pas plus de 2 secondes à s’exécuter.
Au vu de l’appel sleep(4)
, le test ne passera pas et une sortie similaire à celle-ci sera affichée :
On peut y voir que le code du callback a été exécuté, instrumenté par blackfire, envoyé sur blackfire.io, qui nous a renvoyé les résultats des assertions et ont été intégrées dans les résultats des tests unitaires.
Ceci est un cas basé sur le temps d’exécution. Il est possible de définir des tests plus intéressants comme celui-ci :
<?php
namespace Tests\Units;
use Example as TestedClass;
use atoum;
class Example extends atoum
{
public function testExemple()
{
$this
->blackfire
// ajout d'une métrique sur le nombre d'appels à la méthode foo de la classe `Example`, en lui donnant pour nom `example_foo_calls`.
->defineMetric(new \Blackfire\Profile\Metric("example_foo_calls", "=Example::foo"))
// ajout d'une assertion (Blackfire) pour vérifier que la méthode foo ne soit pas appellée plus de 10 fois, en utilisant le nom de la métrique précédement créee.
->assert("metrics.example_foo_calls.count < 10")
// lancement de l'intrumentation du code se trouvant dans le callback (en appellant 12 fois la méthode foo afin de faire échouer le test).
->profile(function() {
$testedClass = new Example();
for ($i = 0; $i < 12; $i++) {
$testedClass->foo();
}
})
;
}
}
Eviter de lancer ces tests
Afin de choisir quand exécuter ces tests, vous pouvez utiliser conjointement le tag @extensions
(voir documentation) et l’extension atoum ruler-extension
qui va vous permettre de filtrer sur les tests nécessitant blackfire ou l’inverse
Par exemple il vous sera possible de lancer tous les tests ne nécessitant pas blackfire :
./vendor/bin/atoum -d tests --filter 'not(extensions contains "blackfire")'
Conclusion
De nombreuses métriques et variables sont disponibles de base.
De plus, vous pouvez rajouter vos propres métriques.
N’hésitez pas à rajouter ces assertions dans vos tests unitaires.
Enfin, cette extension a besoin la dernière version (2.5.0) d’atoum pour fonctionner (voir l’article listant les nouveautés).