uk flag

Mutation testing

Qu est ce que le mutation testing?

Le mutation testing est une méthodologie de test qui consiste à modifier un programme et à analyser les réactions de la suite de tests sur ces modifications. Si les tests réussissent après que le code ait été modifié, alors nous n'avons pas couvert la ligne de code ou les tests ne sont pas très efficaces pour le morceau de code muté.

Cet article ne parlera pas des bénéfices et du fonctionnement du mutation testing, il y a déjà beaucoup d'articles sur ce sujet. Je vous conseille de lire cet article sur Medium: Infection — Mutation Testing Framework, c'est une bonne introduction au mutation testing. L'auteur présente également Infection, l'unique framework de mutation testing existant en PHP. Vous pourrez revenir lire cet article ensuite :)

Mutation testing chez Google

Il est difficile de trouver des articles sur des retours d'expérience ou des best practices sur le mutation testing. Il y a beaucoup d'articles universitaires et très peu d'articles provenant de l'industrie. J'ai toutefois trouvé un document très intéressant de Google à ce sujet : State of mutation testing at google.

Voici un résumé : Google utilise le mutation testing dans leur CI, l'auteur considère que c'est la meilleur manière d'évaluer l'efficacité des tests. Toutefois il y a 2 points sur lequel il faut faire attention:

  • I) Le mutation testing demande beaucoup de ressources, il faut donc utiliser des stratégies pour en utiliser le moins possible :

    Le mutation testing est utilisé seulement sur les lignes ajoutées ou modifiées dans le nouveau commit.

    Pour chaque ligne au maximum un seul mutant est généré. C'est à la fois pour utiliser moins de ressources et pour rendre la review plus lisible. Un mutant est choisi de façon aléatoire dans une reserve de mutants disponibles.

    Le mutation testing n'est pas éxécuté sur les lignes considérées comme "arides" (cf point II).

    Google ne calcule pas de score de mutation global car cela demande trop de ressources.

  • II) L'analyse par les developpeurs des mutants non tués prend beaucoup de temps, il faut donc avoir des stratégies pour améliorer la pertinence de ces mutations :

    Dans leur outil de code review, chaque fois qu'un mutant est généré, le developpeur et les personnes effectuant la revue de code peuvent noter la pertinence de la remontée.

    Ces remontées sont utilisées ensuite pour affiner l'outil et connaitre quels types de mutants sont pertinents sur tel type de code et tel type de langage. Des portions de code peuvent alors être considérées comme "arides" et ne seront pas soumises à des mutations.

    Grace à cette amélioration continue du mutation testing chez Google, l'utilité des remontées est passé de 20% à 80% selon les dev. Actuellement en moyenne ils ont un taux de 87% de mutants tués.

Mutation testing en PHP quand on n'est pas Google

Le document State of mutation testing at google a soulevé 2 points importants . Comment y répondre sur des projets en PHP ?

  • I) Le mutation testing demande beaucoup de ressources, il faut donc utiliser des stratégies pour en utiliser le moins possible :

    Technique n°1: Infection utilise le code coverage généré par Xdebug. Il est possible de réutiliser le code coverage précédemment généré dans une des étapes de votre processus d'intégration continue.

    Technique n°2: muter uniquement les fichiers qui ont été modifiés ou ajoutés dans le nouveau commit.

    Cet article explique comment mettre en place ces 2 techniques dans votre processus d'intégration continue : Mutation testing with infection in big php projects

  • II) L'analyse par les développeurs des mutants non tués prend beaucoup de temps, il faut donc avoir des stratégies pour améliorer la pertinence de ces mutations :

    Il n'existe pas à ma connaissance en PHP d'outils qui nous permette d'avoir des feedbacks sur l'interêt ou pas des mutations dans notre processus d'intégration continue. De plus on ne peut pas faire de calculs aussi fin que Google avec les lignes "arides".

    Infection possède un ensemble de mutants. Via un fichier de configuration, vous pouvez désactiver individuellement des mutants jugés non pertinent de manière itérative. Il est important d'effectuer cette demarche pour limiter le "bruit" des résultats du mutation testing. Par exemple: est-ce-que vous souhaitez utiliser le mutant qui modifie une méthode protected pour la passer en private? Pas moi.

Conclusion

Le mutation testing est un outil très intéressant pour améliorer la qualité de ses tests unitaires. Afin de favoriser son adoption par les développeurs il est important d'utiliser les techniques décrites dans cet article pour avoir un processus d'intégration continue rapide et des mutateurs pertinents.