Testing Things

Hier a eu lieu le Super Apéro PHP organisé par l'AFUP, un événement à ne pas manquer pour les développeurs PHP ! J'ai eu l'occasion d'y donner un talk sur la qualité des tests fonctionnels & unitaires.

J'y ai abordé quelques bonnes pratiques en m'appuyant sur Behat & PHPUnit. Cependant, ces conseils s'adaptent à n'importe quel logiciel de test :-)

Tests fonctionnels

L'avantage certain avec Behat, c'est la séparation entre les features et les contexts. Vous pouvez impliquer votre client (ou à défaut votre chef de projet) dans la rédaction des scénarios, vu que ceux-ci ne sont pas techniques ;-)

Si comme moi vous commencez à avoir plusieurs centaines de scénarios, vous risquez de vous heurter à des soucis de mémoire (Allowed memory size… #çaSentLeVécu). En effet, Behat ne vide pas sa mémoire si l'on exécute l'intégralité des scénarios d'un coup.

Pour cela, je vous recommande d'utiliser toutes les options de Behat : suites, tags, etc… Exécutez Behat par suite ou par tag lui permettra de libérer sa mémoire entre chaque exécution : vendor/bin/behat --tags=@admin.

  • Symfony2 Extension : connecte Behat à votre projet Symfony, et permet d'injecter des services Symfony dans vos contexts;
  • Behatch Contexts : collection de contexts Behat génériques à réutiliser dans vos contexts;
  • ScenarioStateBehat Extension : cache partagé entre contexts pour partager des données dynamiques.

Bonnes pratiques

Je me suis rendu compte rapidement qu'avec toutes ces resources disponibles, les développeurs pouvaient facilement oublier quelques bonnes pratiques. Oui oui, même dans les tests il existe des bonnes pratiques à suivre !

  • Restez positifs : évitez les négations, plutôt que de dire I am not authorized, préférez dire I am unauthorized
  • Rédigez des scénarios non techniques : vous pourrez ainsi impliquer votre chef de projet chéri dans leur rédaction, et vous concentrer sur les contexts
  • Gardez vos scénarios indépendants : il sera alors plus facile de débugger le 35° scénario sans exécuter les précédents
  • BDD is love, BDD is life : commencez par rédiger les tests fonctionnels avant les développements, il sera plus facile de les tester

Je vous recommande de jeter un oeil aux slides de Samuel ROZE Behat c'est plus que ça : http://fr.slideshare.net/samuelroze/behat-cest-plus-que-a-behat-is-more-than-that.

Oui, mais alors : comment je gère les données de mes scénarios ?

La réponse est simple : purgez les données au début de chaque scénario (@BeforeScenario en Behat), puis chargez juste celles dont vous avez besoin. L'ORM Purger de Doctrine vous permet facilement de vider votre base, et ce ne sont pas les outils qui manquent pour créer des fixtures : DoctrineFixturesBundle, HautelookAliceBundle, etc…

Tests unitaires

Une fois que notre projet est testé, on peut optimiser notre code sans créer de nouveaux bugs : les tests fonctionnels sont là pour prévenir l'introduction de bugs.

Au-delà de tester une portion du programme (cf. définition d'un test unitaire), est d'autant plus intéressante qu'elle met en évidence la qualité du code grâce à l'utilisation des mocks.

Dès que vous imbriquez des mocks pour vos tests unitaires, vous ne respectez alors peut-être pas la Loi de Déméter : ne parlez qu'à vos amis immédiats. Dans vos objets, vous ne devez appeler que les méthodes de vos dépendances directes.

Respecter la Loi de Déméter simplifiera vos tests et votre code, et ce dernier sera optimisé :-).

Enfin, donnez-vous un objectif de couverture de code : il ne sert à rien de viser 100%, vous passerez du temps sur des tests n'apportant que peu de valeur à la qualité de votre code. Commencez par un objectif réaliste, 40%, puis augmentez cet objectif au fil des développements. Cela vous permettra même d'appliquer la Boy Scout Rule : rendez le code plus propre après votre passage ;-).

Hey, mes super-slides-de-la-mort-qui-tue sont disponibles ici : https://fr.slideshare.net/VincentCHALAMON/testing-things.