PHP - Infection

Infection est une libraire de test créée par Maks Rafalko qui se distingue d’autres par le fait de faire du “mutation testing”. L’idée est d’introduire des modifications dans votre code (des mutations) pour voir si vos tests (Phpunit, Phpspec, Pest, Codeception) détectent ces modifications. S’ils les détectent, ça veut dire que vos tests couvrent bien les scénarios possibles, s’ils ne les détectent pas, ça veut dire que vos tests sont incomplets.

De mon point de vue, ce n’est pas si simple de penser à tous les cas de tests. Il est souvent relativement facile de tester le scénario nominal (quand tout va bien) et certains scénarios d’erreurs, mais trouver les cas aux limites peut-être compliqué. Infection permet, sans trop se poser de question, de voir apparaitre ces cas aux limites.

Quelques exemples de mutations que peut introduire Infection :

  • transformer un > en <
  • incrémenter une valeur
  • décrémenter une valeur
  • enlever un élément d’un tableau
  • enlever l’appel d’une méthode
  • changer la visibilité d’une méthode

Après son exécution, Infection va donner des métriques :

  • Mutation Score Indicator (MSI)
  • Mutation Code Coverage
  • Covered Code MSI

Le MSI vous donne le pourcentage de mutations détectées. Il faut donc essayer de se rapprocher de 100%. Si tel est le cas, ça veut dire que vos tests couvrent l’ensemble des scénarios possibles (bravo) de votre application.

Le “Mutation Code Coverage” est relativement semblable au “code coverage” classique.

Enfin, le “Covered Code MSI” donne le pourcentage de mutations détectées sur la zone couverte par votre code. S’il se rapproche de 100%, cela veut dire que le vos tests testent bien tout ce qu’ils couvrent.

Environnement de developpement

Infection peut être lancer en local, souvent avant de commiter (ou de pusher). Mais attention, cela peut être assez long, beaucoup plus que de lancer vos tests PHPUnit en tout cas. Heureusement, la documentation officielle fournissent des pistes pour optimiser ça.

Vous pouvez, par exemple, lancer Infection uniquement sur les fichiers modifiées et de ce fait, diminuer le nombre de tests lancés.

Vous pouvez également utiliser plusieurs “threads” pour exécuter les tests en parallèles. Ceci va quasiment diviser par N (nombre de “threads”) le temps d’exécution.

Malgré ça, si vous êtes sur une grosse application (ou sur une grosse PR 😱), ça peut quand même être long. Ce n’est clairement pas le genre d’outils qu’on lance à chaque changement de notre code. En revanche, ça peut être très intéressant de l’intégrer à la CI.

Intégration continue

Utiliser Infection dans votre CI permet, comme pour n’importe quel framework de tests, de bloquer le merge d’une pull request en cas d’echec.

Il y a quelques options particulièrement utiles en CI :

./infection.phar --min-msi=90 --min-covered-msi=70

Celles-ci vont vous permettre de définir un seuil minimal à atteindre pour le MSI et le “covered code MSI” sans quoi le build va fail et le merge sera bloqué. Cela va assurer une certaine couverture de “bons” tests à votre projet !

Conclusion

Infection fait partie des outils très importants dans l’univers PHP. Il rend nos tests meilleurs et plus pertinents et nos applications plus solides.

Il est à utiliser sans modération que ce soit en local ou en CI mais il faut se pencher en détails sur sa configuration pour en tirer le maximum et être le plus efficace possible.