Aller au contenu
SDETRole
SDETRole

Glossaire · Fondamentaux du test

Test de mutation

En anglais : Mutation testing

Également appelé : tests de mutation, analyse de mutation, score de mutation, mutation score

Définition

Technique qui injecte de petits bugs volontaires (mutants) dans le code puis relance les tests pour mesurer si la suite détecte réellement les défauts.

Le test de mutation teste vos tests. Un outil crée de nombreuses copies du code, chacune avec une petite modification, par exemple >= transformé en >, + en -, ou le corps d’une méthode remplacé par return null. Chaque copie modifiée est un mutant. La suite de tests s’exécute contre chaque mutant. Si au moins un test échoue, le mutant est tué. Si tous les tests passent encore, le mutant a survécu, ce qui signifie que les tests ne remarqueraient pas ce bug.

Score de mutation = mutants tués / total des mutants (hors mutants équivalents).

Exemple

boolean isAdult(int age) {
    return age >= 18;
}

Tests : isAdult(30) vaut true, isAdult(10) vaut false. La couverture de lignes et de branches est de 100 %.

L’outil crée un mutant avec age > 18. Les deux tests passent toujours, donc le mutant survit. Cela révèle un test de valeur limite manquant : personne n’a vérifié isAdult(18). L’ajouter tue le mutant. La couverture ne pouvait pas vous le dire ; le test de mutation, si.

Outils

  • Java : PIT (pitest), avec des plugins Maven et Gradle et la prise en charge de JUnit 5.
  • JavaScript/TypeScript : StrykerJS, qui existe aussi en versions .NET et Scala.
  • Python : mutmut et Cosmic Ray.

Limites pratiques

  • Coût. Chaque mutant correspond à une exécution de tests. Les outils réduisent ce coût en n’exécutant que les tests qui couvrent la ligne mutée et en travaillant de façon incrémentale sur le code modifié, mais cela reste bien plus lent qu’une exécution normale. La plupart des équipes le lancent la nuit, ou sur les fichiers modifiés dans une pull request, et non à chaque commit sur toute la base de code.
  • Mutants équivalents. Certaines modifications ne changent en rien le comportement, par exemple transformer i < n en i != n dans une boucle où i augmente toujours de un en partant d’une valeur inférieure à n. Aucun test ne peut les tuer : il faut donc les examiner et les exclure à la main.
  • Idéal au niveau unitaire. Le test de mutation est conçu pour des tests unitaires rapides et déterministes. L’exécuter sur des tests d’interface lents est rarement réaliste.

Servez-vous des mutants survivants comme d’une liste de tâches pour les assertions manquantes, en particulier dans la logique métier, plutôt que de courir après un score parfait.

Saisissez un terme pour rechercher sur SDETRole.

Recherche plein texte par Pagefind · s’exécute dans votre navigateur Ouvrir la page de recherche →