https://d226lax1qjow5r.cloudfront.net/blog/blogposts/converting-your-test-suite-to-pest/shifting-to-pest.png

Convertir votre suite de tests en PEST

Publié le December 16, 2021

Temps de lecture : 11 minutes

Changer la façon dont j'écris le code grâce au développement piloté par les tests a franchement changé mes capacités en tant que programmeur. Soudain, je pouvais écrire des services et des fonctionnalités en toute confiance - je ne comprends pas pourquoi tant d'entreprises encore "C'est un mystère pour moi de savoir pourquoi tant d'entreprises continuent à ne pas avoir le temps de faire des tests, et ce depuis longtemps, PHPUnit a été l'outil de choix de facto pour l'écriture de PHP TDD.

Un nouveau projet a vu le jour récemment et pourrait changer la donne. Il existe bonne documentation et une communauté de rencontre qui se construit autour de lui et qui se révèle être une option attrayante pour les développeurs. Je fais bien sûr référence à PEST, et j'ai donc pensé à l'essayer sur notre propre site. SDK PHP de Vonage.

La suite actuelle

Notre SDK PHP Vonage a fait l'objet d'une maintenance complète au fil des ans, et contient donc une suite de tests complète. Bien qu'il ne soit pas d'une portée " d'entreprise ", il s'agit néanmoins d'un exercice utile pour tester le PEST.

La suite actuelle sur cette branche a 831 tests réussis qui exécutent 4039 assertions. Il y a 9 tests ignorés et 15 tests incomplets. Le temps d'exécution total est de 13:54 en PHP8.

Screenshot of total tests showing 9 skipped and 15 incomplete tests.Screenshot of total tests showing 9 skipped and 15 incomplete tests.

Pour l'anecdote, il s'exécute assez correctement et l'un de ces tests est en fait un test de dépassement de délai qui fait grimper le temps. Le but ici n'est pas d'améliorer le runner, mais de le modifier pour voir ce qui se passe. Notre premier port d'appel est d'installer installer PEST et de l'exécuter. L'une des caractéristiques les plus importantes de PEST est que il est complètement compatible avec PHPUnitet peut donc être utilisé de manière interchangeable, quelle que soit la syntaxe utilisée. Cela nous permet d'installer PEST, de l'exécuter pour voir les résultats et éventuellement d'essayer et d'implémenter les récentes fonctionnalités de tests parallèles parallèle.

Pour installer PEST, j'exécute la commande suivante dans la ligne de commande :

composer require pestphp/pest

Il semble faussement facile qu'une commande de composition plus tard, je puisse exécuter PEST. Il est bon de noter, cependant, que le dépôt sur lequel il fonctionnera a déjà des exigences - l'une de ces exigences est une version minimale de PHP de 7.3. PEST a déjà une version minimale requise de PHP de 7.3 et plus, donc il n'y a pas de bricolage à faire pour se mettre à jour.

Il est temps de lancer PEST et de voir ce qui se passe :

./vendor/bin/pest

La première chose que vous remarquerez est que PEST utilise un format de sortie similaire à l'argument --testdox pour formater la sortie de PHPUnit. La sortie est plutôt agréable :

Test screenshot, showing a time of 13.21 seconds.Test screenshot, showing a time of 13.21 seconds.

Hmm, donc 13,28 secondes, hein ? Eh bien, c'est en fait plus rapide rien qu'avec le coureur. Et si nous essayions d'utiliser la fonction parallèle de PEST ? Il s'agit d'un paquet séparé, alors allons le chercher :

composer require pestphp/pest-plugin-parallel

Et maintenant, il faut le faire fonctionner :

./vendor/bin/pest -parallel

Et... oh. On dirait que notre chance a tourné :

Screenshot of a PHP bug.Screenshot of a PHP bug.

Une rapide recherche sur Google révèle qu'il y a un bogue dans PHP lui-même pour cela, comme documenté dans le journal des problèmes de PHPUnit :

https://github.com/sebastianbergmann/phpunit/issues/4305

Je suppose que c'est le prix à payer pour être un peu à la pointe du progrès.

Photo of frustrated person looking at their laptop screen.Photo of frustrated person looking at their laptop screen.

Syntaxe PHPUnit vs. PEST

J'ai joué avec le test runner, mais je n'ai pas montré le code ou expliqué l'objectif réel de PEST.

Membre du noyau de Laravel Nuno Madro a créé PEST, un nouveau cadre modelé sur la syntaxe du framework Jest le framework Javascript. C'est tout à fait conforme à la tendance actuelle de PHP (et en particulier de Laravel) d'évoluer vers une syntaxe plus fonctionnelle, basée sur les fermetures, qui s'apparente à la façon dont le Javascript est écrit. Il est donc logique que vos tests backend PHP pour votre application web full stack soient écrits dans une syntaxe similaire à celle de vos tests front-end. Voici un exemple "avant et après" du SDK PHP de Vonage :

class NumberTest extends VonageTestCase  
{  

 /**  
 * @var Number;  
 */
 protected $number;  
  
 public function setUp(): void  
 {  
	$this->number = new Number('14843331212');  
 }  
 
 public function testNumberConstructor(): void  
 {   
	$this->assertEquals('14843331212', $this->number->getNumber());  
 }

Nous utilisons ici un certain nombre de modèles communs - la méthode magique setUp() s'exécute avant que les tests ne soient exécutés, puis nous utilisons assertEquals() qui est une classe d'aide de PHPUnit TestCase (dans notre exemple, VonageTestCase l'étend plus haut).

Maintenant, je vais vous montrer le même test, mais écrit en syntaxe PEST :

use Vonage\Numbers\Number;  
  
beforeEach(function () {  
   $this->number = new Number();  
});  
  
test('number constructor', function () {  
   expect($this->number->getNumber())->toEqual('14843331212');  
});

C'est un bon exemple de l'écosystème PHP qui, en général, se tourne vers le Javascript pour trouver de nouvelles idées - comme vous pouvez le voir, la syntaxe de PEST est très similaire à celle de JEST. Cela montre également l'une des valeurs fondamentales de PEST, qui est d'avoir un enchaînement de méthodes plus fluide dans l'API afin d'écrire moins de code, ce qui est une approche très proche de la philosophie de Laravel. Nous avons maintenant un ordre supérieur beforeEach() avec une fermeture à l'intérieur qui sera exécutée avant chaque test, et maintenant les structures de fonctions PHP classiques de PHPUnit ont été remplacées par une syntaxe plus fonctionnelle. Cet exemple montre également comment l Expectation API est conçue pour enchaîner les assertions d'une manière humainement lisible avec des noms de méthodes tels que expect(true)->toBe(value) ou expect($variable)->toBeArray().

OK, alors l'automatisation ?

Je vais être honnête, cela ne s'est pas passé comme je l'aurais voulu. Je vais cependant vous montrer pourquoi.

J'ai pris connaissance de cette information sur Twitter qu'il était possible d'utiliser un outil pour convertir automatiquement votre suite PHPUnit en PEST, que le code soit dans Laravel ou non. Je me suis donc rendu sur le site de Pest Converter et et j'ai mis en place un dépôt et une branche pour l'essayer. Une fois lancé, Shift va créer une nouvelle branche à partir de la branche de base que vous fournissez et créer des commits d'étapes logiques pour se déplacer à travers la syntaxe. L'une des choses à faire en premier était de changer le dossier test/ en tests/ afin que le convertisseur sache où chercher vos tests.

Cependant, lors de l'exécution de PEST après la conversion :

Screenshot showing PestxceptionsestCaseClarrOrTrailNotFound.Screenshot showing Pest\Exceptions\TestCaseClarrOrTrailNotFound.

Hmm. Ce n'est donc pas un long fleuve tranquille. Il convient de noter que je ne savais pas du tout à quoi m'attendre, et ce pour plusieurs raisons :

  • Le SDK PHP de Vonage est indépendant du cadre de travail.

  • Il dépend de la Prophesize de la bibliothèque

  • Un certain nombre de caractéristiques PHP sont utilisées, ce qui rend la suite de tests légèrement plus complexe

Plutôt que d'utiliser la composition traditionnelle, PEST utilise un modèle de configuration différent. PEST dispose d'un pest.php qui vous permet de spécifier des fonctions d'aide, des traits et des méthodes communes telles que RefreshDatabase. Vous pouvez également spécifier les dossiers auxquels vous souhaitez que les classes soient appliquées, comme suit :

uses(\VonageTest\HTTPTestTrait::class)->in('Secrets');

La raison pour laquelle le convertisseur PEST ne peut pas les résoudre est un certain nombre de cas limites. Une chose soulignée par Laravel Shift's Jason McCreary dans nos conversations d'assistance, c'est que certains tests définissent un conteneur d'Applications en $this->appce qui entre en conflit avec l'infrastructure d'application de Laravel (puisqu'il ne sait pas si vous avez une application Laravel ou non).

Conclusions

Bien que le convertisseur PEST ait trouvé difficile d'automatiser le transfert des tests, cela m'amène à deux conclusions :

  • Laravel Shift, les créateurs de Pest Converter, sont déjà en train d'examiner les cas limites de notre bibliothèque que j'ai utilisée et de travailler sur la façon de les gérer, mais le plus important, c'est qu'ils sont en train de travailler sur les cas limites de notre bibliothèque que j'ai utilisée et de travailler sur la façon de les gérer.

  • Ne lancez pas le convertisseur si votre suite de tests est complexe ou trop élaborée - corrigez-la d'abord.

Comme pour toute chose, il y a des risques à entreprendre une refonte majeure par le biais de l'automatisation. Dans notre cas, le risque est que nous avons affaire à une bibliothèque PHP brute sans cadre. Cependant, Shift travaille sur la mise à jour via une branche cible, puis crée la branche Shift à partir de celle-ci afin de minimiser les risques. Si elle ne fonctionne pas, ne la fusionnez pas ! Vous avez également la possibilité d'utiliser le programme Human Shift qui aboutira inévitablement à une suite entièrement convertie.

Ce que je conseillerais, c'est que si vous avez une application Symfony ou Laravel, ce convertisseur est absolument conçu avec ces cas à l'esprit, donc le Shift sera assez solide.

Devriez-vous adopter PEST ? Comme toujours, c'est à vous de décider. Si vous voulez rester à la pointe des choses qui changent en PHP, alors c'est certainement une option attrayante. Gardez à l'esprit que la façon dont PEST structure sa syntaxe est naturellement en ligne avec l'approche de Laravel pour les flux d'API, donc il a le potentiel de confondre vos développeurs si vous utilisez quelque chose d'autre de populaire comme Symfony, CakePHP ou Drupal.

Partager:

https://a.storyblok.com/f/270183/400x385/12b3020c69/james-seconde.png
James SecondeDéveloppeur PHP senior Advocate

Acteur de formation avec une thèse sur la comédie, je suis venu au développement PHP par le biais de la scène des rencontres. Vous pouvez me trouver en train de parler et d'écrire sur la technologie, ou de jouer/acheter des disques bizarres de ma collection de vinyles.