PHPUnit vs Behat

Créé le 05/04/2021

Dernière mise à jour le 05/04/2021

Sur mon site, je n’ai qu’une seule fonctionnalité faite avec du code spécifique, l’envoi d’un email de notification lorsqu’un commentaire est créé. Le reste du code spécifique correspond au thème et aux migrations de contenu (quand j’ai migré depuis Drupal 7).

Même s’il s’agit d’une fonctionnalité simple, je me suis dit que ce serait intéressant de tester la même fonctionnalité avec 2 approches, l’une via PHPUnit et l’autre via Behat pour avoir des points de comparaison.

Afin de partager le code réalisé j’ai créé le snippet suivant : https://gitlab.com/-/snippets/2100504

PHPUnit

Voir cet article pour une explication des tests PHPUnit et sur leur mise en place des tests dans Drupal.

Pour réaliser la fonctionnalité d’envoi d’email, j’ai implémenté un hook_comment_entity_insert() pour agir lors de la création d’un commentaire.

Comme ce hook est déclenché aussi bien pour un commentaire créé via du code que via un formulaire de commentaire, j’ai fait 2 tests (dans des fichiers différents car avec setup différent) :

  • testCommentMailSend() : pour tester lors de la création d’un commentaire peu importe la source
  • testCommentFormMailSend() : pour tester lors de la soumission d’un formulaire de commentaire

Pour le second test, comme le commentaire créé n’est pas disponible en variable directement, il faut le charger manuellement. J’aurai pu passer par le service entityTypeManager mais j’ai préféré utiliser ce que j’avais à disposition en suivant un comportement front, c’est-à-dire être redirigé sur une URL avec le numéro du commentaire en paramètre.

Behat

Behat est un framework de tests PHP « piloté par la comportement ». Les tests sont écrits en langage Gherkin, un langage d’écriture de tests compréhensible par le métier, les tests suivent la structure suivante :

  • en tant que X
  • si je fais Y
  • alors je m’attends à Z

Une configuration simple pour Behat est d’utilisé le navigateur Goutte qui est un navigateur PHP headless, il ne va pas interpréter le JS.

En behat, le test fait une quinzaine de lignes, compréhensibles par n’importe qui.

Les difficultés rencontrées ont été :

  • adapter la configuration Behat, fichier behat.yml :
    • mettre les noms des régions que j’utilise sur mon thème (Bootstrap)
    • changer les sélecteurs de messages et de certains textes car traduits en français
  • des effets de bords de Goutte, comme le navigateur n’interprète pas le JS :
    • j’utilise le module Antibot comme anti-spam, or il considère que si le JS n’est pas interprété, il s’agit d’un robot. Le plus compliqué a été de comprendre pourquoi j’avais des erreurs là où un test sur un site sans Antibot fonctionnait. Une fois le problème identifié, il a été simple de désactiver la protection dans les tests.
    • même si le test sur l’email fonctionnait, j’ai eu envie de vérifier que le message de confirmation de saisi d’email fonctionnait. Or j’utilise Big Pipe sur mon site, et bien que Big Pipe soit capable de s’adapter si le navigateur n’interprète pas le JS, Goutte n’envoie pas explicitement l’information que le JS n’est pas interprété. Résultat impossible de tester un message Drupal. Il y a cette issue qui est en cours sur l’extension Drupal pour Behat.

Comparaisons

Behat

Une fois la configuration Behat prête, s’il n’y avait pas les effets de bord liés au JS, l’écriture des tests est assez fluide.

Là où les tests PHPUnit s’adressent à des développeurs, les tests Behat peuvent être écrits par d’autres profils.

Quelques points d’attention :

  • si jamais il faut débugger, il faudra éditer le code Behat pour pouvoir avoir accès aux messages d’erreurs
  • je me suis contenté d’utiliser les features à disposition dans Behat et l’extension Drupal pour Behat, s’il y a besoin de coder des features Behat propres à un projet, là il faudra un profil de développeur
  • les chaînes de caractères dans les tests sont en français, sur un site multilingue cela peut compliqué la détection de l’origine d’un problème. Les tests peuvent échouer car la traduction importée n’est plus la bonne, ou parce qu’il y a effectivement un autre problème

PHPUnit

Autant l’écriture du test en Behat est simple, autant je n’ai pas exactement testé les mêmes points qu’avec PHPUnit.

Avec les tests PHPUnit, j’ai pu facilement tester des variables générées et donc tester le contenu complet de l’email envoyé. Ce qui aurait été complexe à ma connaissance sans feature dédiée.

Temps d’exécution

Temps d’exécution pris sur l’exécution des tests dans Gitlab CI.

PHPUnit : 122s

  • testCommentFormMailSend() : 99s
  • testCommentMailSend() : 22s

Behat : 5s

Les tests Behat sont bien plus rapides car s’effectuant sur un environnement existant, où le site n’est pas réinstallé à chaque test.

Concernant les tests PHPUnit, j’ai utilisé des tests Functional pour rester simples dans l’écriture des tests, avec des tests Kernel cela aurait été déjà bien plus rapide.

Et l’on peut constaté que le test testCommentMailSend() est bien plus rapide, cela pour 2 raisons :

  • il ne fait pas de requête sur le front Drupal, donc pas de sollicitation de la couche de rendu
  • ses pré-requis sont bien plus réduits, donc lors de l’installation pour ce test, il y a moins de modules à activer et de configurations à importer.

Conclusion

Il s’agit de 2 outils différents qui n’ont pas les mêmes avantages et inconvénients et peuvent être complémentaires.

Selon, par exemple :

  • le setup projet
  • le profil de la personne chargée des tests
  • ce qu’il y a à tester
  • les besoins de performance

cela fait autant de critères pour décider de s’orienter vers l’un ou l’autre des outils, où les 2.

Ajouter un commentaire