Qu’est-ce que le test de mutation ? (Exemple)
⚡ Résumé intelligent
Les tests de mutation consistent à introduire délibérément de petits défauts dans le code source, puis à exécuter la suite de tests existante sur chaque version défectueuse, afin de déterminer si ces tests sont suffisamment robustes pour détecter le changement.
Qu’est-ce que le test de mutation ?
Test de mutation Le test par mutation est un type de test logiciel où certaines instructions du code source sont modifiées afin de vérifier si les cas de test parviennent à détecter les erreurs. L'objectif du test par mutation est de garantir la robustesse des cas de test, en s'assurant qu'ils échouent face au code source modifié.
La modification apportée à un programme mutant doit être extrêmement minime afin de ne pas affecter l'objectif global du programme. Le test par mutation est également appelé stratégie de test basée sur les défauts, car il consiste à créer délibérément un défaut dans le programme. Il s'agit d'une forme de Blanc Box Tests qui s'applique principalement pendant Tests unitaires.
Les tests de mutation ont été proposés en 1971 dans un mémoire étudiant de Richard Lipton et formalisés en 1978 dans l'article « Hints on Test Data Selection » de DeMillo, Lipton et Sayward. Leur essor a été freiné par le coût de calcul de l'époque, mais ils ont depuis regagné du terrain pour des langages tels que… Java, C#, Python, JavaScript et XML.
Comment exécuter des tests de mutation ?
Voici les étapes à suivre pour réaliser un test de mutation, également appelé analyse de mutation :
Étape 1 : Des erreurs sont introduites dans le code source du programme en créant de nombreuses versions appelées mutants. Chaque mutant doit contenir une seule erreur, et l'objectif est de provoquer l'échec de la version mutante, ce qui démontre l'efficacité des tests.
Étape 2 : Les cas de test sont appliqués au programme original ainsi qu'au programme mutant. Cas de test devrait être adéquat, et il est modifié pour détecter les défauts dans un programme.
Étape 3 : Comparez les résultats du programme original et du programme mutant.
Étape 4 : Si le programme original et le programme modifié produisent des résultats différents, le programme modifié est éliminé par le test. Par conséquent, le test est suffisamment efficace pour détecter la différence entre le programme original et le programme modifié.
Étape 5 : Si le programme original et le programme mutant produisent le même résultat, le mutant est conservé. Dans ce cas, il est nécessaire de créer des cas de test plus efficaces qui éliminent tous les mutants.
Le diagramme ci-dessous tracIl s'agit des mêmes cinq étapes, du programme original à la génération de mutants jusqu'au verdict de survie ou de mort.
Comment créer des programmes mutants ?
Une mutation est simplement une modification syntaxique apportée à une instruction de programme. Chaque programme mutant doit différer du programme original par une seule mutation.
| Programme original | Programme mutant |
| Si (x>y) Imprimer « Bonjour » Else Imprimer « Bonjour » |
Si (x Imprimer « Bonjour » Else Imprimer « Bonjour » |
Dans la paire ci-dessus, seul l'opérateur de comparaison a changé ; pourtant, un test où x est supérieur à y affiche désormais « Hi » au lieu de « Hello ». L'illustration montre cette unique modification syntaxique.
Que changer dans un programme Mutant ?
Plusieurs techniques permettent de générer des programmes mutants. Les trois familles ci-dessous couvrent la plupart des opérateurs de mutation fournis avec les outils.
| Operaet opérateurs de remplacement | opérateurs de modification d'expression | opérateurs de modification de déclaration |
| Remplacez l'opérande par un autre opérande (x par y, ou y par x) ou par une valeur constante. | Remplacez un opérateur, ou insérez un nouvel opérateur, dans une instruction de programme. | Les instructions programmatiques sont modifiées pour créer des programmes mutants. |
| Exemple : Si (x> y) remplace les valeurs x et y Si(5>y) remplacer x par la constante 5 |
Exemple : Si(x==y) On peut remplacer == par >= et obtenir le programme mutant comme suit : If(x>=y) et insertion de ++ dans l'instruction Si(x==++y) |
Exemple : Supprimez la partie else dans une instruction if-else Supprimez l'intégralité de l'instruction if-else pour vérifier le comportement du programme. |
Quelques exemples d'opérateurs de mutation :
- Remplacement de l'étiquette GOTO
- Remplacement de la déclaration de retour
- Suppression de la déclaration
- Insertion d'opérateurs unaires (tels que – et ++)
- Remplacement du connecteur logique
- Remplacement de nom de tableau comparable
- Supprimer la partie else d'une instruction if-else
- Ajout ou remplacement d'opérateurs
- Remplacement de l'instruction en modifiant les données
- Modification des données pour les variables
- Modification des types de données dans le programme
OperaLes tores qui touchent une condition limite survivent le plus souvent, de sorte que les résultats de mutation pointent fréquemment vers des lacunes dans analyse des valeurs limites.
Types de tests de mutation
In Génie logicielLes tests de mutation sont fondamentalement catégorisés en trois types : mutation de déclaration, mutation de valeur et mutation de décision.
- Mutation de déclaration – une instruction est coupée, collée ou supprimée, ce qui peut entraîner la suppression de certaines lignes de code.
- Mutation de valeur – les valeurs des paramètres et constantes principaux sont modifiées, par exemple en changeant une limite de boucle ou un seuil.
- Mutation de décision – les instructions de contrôle sont modifiées, par exemple flipping un opérateur relationnel ou la négation d'une condition.
Les outils regroupent leurs opérateurs sous ces trois rubriques, de sorte que la famille ayant produit un mutant survivant indique au testeur quel type d'assertion est manquant. Un mutant de décision survivant marque généralement une branche non testée, qui chevauche avec test en boucle.
Automatisation des tests de mutation
Les tests de mutation sont extrêmement longs et complexes à réaliser manuellement ; il est donc conseillé d’utiliser des outils d’automatisation, ce qui permet également de réduire les coûts. Un outil de test de mutation compile les mutants, planifie les exécutions, enregistre le mutant éliminé lors de chaque échec et génère un rapport de score.
Liste des outils disponibles :
- Stryker — un framework de test de mutation open source avec des éditions pour JavaScénario et TypeScript (StrykerJS), C# et .NET (Stryker.NET), et Scala (Stryker4s).
- PIT, également écrit PITest — un système de test de mutation pour Java et la JVM qui modifie le bytecode compilé et s'intègre à Maven et Gradle constructions à côté JUnit.
Les deux s'exécutent en tant qu'étape de compilation, elles appartiennent donc au même groupe. intégration continue pipeline comme le reste du tests d'automatisation suite.
Score de mutation
Le score de mutation est défini comme le pourcentage de mutants éliminés par rapport au nombre total de mutants.
Score de mutation = (Mutants tués / Nombre total de mutants) * 100
La formule est présentée ci-dessous sous la forme que la plupart des outils affichent.
Les cas de test sont considérés comme adéquats en termes de mutation lorsque le score atteint 100 %. En pratique, le dénominateur doit exclure mutants équivalents — des mutants dont la syntaxe modifiée se comporte exactement comme l'original, de sorte qu'aucun test ne peut les éliminer. Les outils indiquent donc le nombre de mutants éliminés divisé par le nombre total de mutants non équivalents éliminés et survivants, et permettent au testeur de signaler les équivalents.
Les résultats expérimentaux ont démontré que les tests de mutation constituent une méthode efficace pour évaluer la pertinence des cas de test. Leur principal inconvénient réside dans le coût de génération des mutants et d'exécution de chaque cas de test sur chacun d'eux.
Tests de mutation vs Code Couverture
Haute Couverture de test Cela ne prouve pas la robustesse des tests. La couverture de lignes et de branches enregistre les instructions exécutées, et non si des vérifications ont été effectuées par la suite. Ainsi, un test qui appelle une méthode sans effectuer aucune assertion est tout de même considéré comme couvert. Les tests de mutation comblent cette lacune, car un mutant ne s'arrête que lorsqu'une assertion échoue.
| Aspect | Code couverture | Score de mutation |
| Ce qu'il mesure | Quelles lignes ou branches les tests ont-ils exécutées ? | Quels défauts injectés les tests ont-ils détectés ? |
| Sensible aux affirmations | Non, un test sans assertions ajoute tout de même de la couverture | Oui — un mutant survit lorsqu'aucune assertion n'est fausse. |
| Coût d'une course | Un essai instrumenté | Un essai par mutant survivant, jusqu'à présent beaucoup plus lent |
| Utilisation typique | Un contrôle rapide sur chaque commit | Un contrôle périodique plus approfondi des modules critiques |
| Mode de défaillance | Couverture à 100 % sans véritable vérification | Des mutants équivalents qui ne peuvent jamais être tués |
Ces deux indicateurs sont complémentaires. La couverture désigne le code qui n'a jamais été atteint ; le score de mutation désigne le code atteint qui n'a jamais été vérifié. Tous deux alimentent la même source. processus de gestion des défauts, parallèlement à des mesures telles que densité de défauts.
Avantages des tests de mutation
Voici les avantages des tests de mutation :
- Il s'agit d'une approche efficace pour obtenir une couverture élevée du programme source.
- Il teste la suite de tests elle-même, ce qu'aucun autre technique de test logiciel le fait directement.
- Les tests de mutation offrent un bon niveau de détection d'erreurs aux développeurs de logiciels.
- Cette méthode permet de déceler les ambiguïtés du code source et de mettre au jour des défauts que les exécutions ordinaires ne détectent jamais.
- Les mutants survivants sont exploitables : chacun d’eux nomme une ligne spécifique et un changement spécifique que la suite n’a pas détecté.
- Ces tests permettent aux clients de bénéficier d'un système plus fiable et plus stable.
Inconvénients des tests de mutation
En revanche, voici les inconvénients des tests de mutation :
- Les tests de mutation sont extrêmement coûteux et chronophages, car un grand nombre de programmes mutants doivent être générés et compilés.
- Étant donné que cette opération est chronophage, il est juste de dire que ce test ne peut être réalisé sans outil d'automatisation.
- Chaque mutant est testé par le même nombre de cas de test que le programme original ; il faut donc exécuter une population importante de mutants sur l'ensemble de la suite de tests.
- Les mutants équivalents ne peuvent être tués par aucun test, et leur distinction des véritables survivants nécessite généralement un examen manuel.
- Comme la méthode modifie le code source, elle n'est pas applicable à Noir Box Tests.
Quand utiliser les tests de mutation
Le profil de coûts ci-dessus indique que les tests de mutation sont rarement exécutés sur l'ensemble du code source à chaque commit. Ils sont rentables lorsqu'une erreur non détectée coûte cher et que le code testé est suffisamment petit pour muter rapidement.
- Logique critique pour la sécurité ou financière — calcul des paiements, règles fiscales et contrôles d'autorisation, où une mauvaise réponse silencieuse est pire qu'un accident.
- Suites avec une couverture anormalement élevée — lorsque la couverture est proche de 100 %, mais que des défauts persistent.
- Code existant en cours de refactorisation — Les résultats des mutations révèlent si les tests existants permettraient de détecter une régression.
- Bibliothèques et composants partagés — un défaut dans un produit réutilisé composant se multiplie pour chaque appelant.
- Équipes s'entraînant développement piloté par les tests — le système de vérification des scores permet de s'assurer que les tests écrits en premier sont réellement efficaces.
Il est généralement inutile de l'exécuter sur des prototypes jetables, sur du code d'interface léger ou généré sans logique de branchement, ou sur des suites dominées par des processus lents. tests d'intégration qui prennent déjà des heures pour un seul passage.
La plupart des équipes limitent donc l'analyse aux fichiers modifiés, définissent un seuil pour les modules importants et laissent le reste de l'équipe s'en charger. les tests de régression La suite transporte le reste de la cycle de vie des tests logiciels.



