Infection : Un Framework de test basé sur les mutations

Ce n’est pas une défaillance de votre ordinateur, n’essayez donc pas de régler votre code. Nous avons le contrôle total de vos tests : contrôle des tests unitaires, contrôle de la couverture de code. Nous pouvons aussi bien supprimer vos méthodes que modifier une valeur. Pour l’heure qui vient, asseyez-vous tranquillement. Nous contrôlerons tout ce que vous allez voir. Vous allez participer à une grande aventure et faire l’expérience du mystère avec “Au-delà de vos tests !”

On se croirait dans Au-delà du réel !

On va parler un peu d’Infection – PHP Mutation Testing Framework

Si comme moi vous aimez la satisfaction client, vous devez sûrement écrire des tests.

Comment avoir un code propre, fonctionnel et durable sans tests ? Écrivez un article sur le sujet et je serai le premier à le lire !

Infection

Le principe en quelques lignes.

  • Infection exécute vos tests en premier lieu. Grâce à eux, il va générer des mutants.
  • Un mutant est une modification, très simple, de votre code. Grâce à ça, votre test va être rejoué avec cette modification.
  • Si votre test est robuste, le mutant est tué !

Par exemple, supprimer une ligne dans votre code, ou retirer le mot clef “throw” pour une Exception ou remplacer une division par une multiplication etc.

La liste de tous les mutators comme ils aiment à s’appeler est ici.

Mutant

Lorsqu’on exécute Infection, un fichier de log est généré avec des morceaux de ce genre :

Plusieurs choses à lire :

  • [M] Throw_ : Mutant de catégorie Exceptions
  • On voit qu’il a supprimé le mot clef throw

Si on traduit le langage du mutant en français, ça donnerait :

“Moi le mutant Throw_, j’ai exécuté ton test que tu pensais complet, et pourtant j’ai supprimé un seul mot, et ton test est toujours vert ! Haha, que réponds-tu à ça ?!”

Voilà grosso-modo ce qu’il nous dit..

Donc pour tuer ce mutant et ainsi augmenter notre score, il faut simplement écrire un test.

On ne verra pas ici comment écrire des tests !

Allez encore 320 mutants !

Un des plus courants que l’on rencontre, c’est MethodeCallRemoval.

Le mutant ici nous dit :

“J’ai enlevé l’appel à la méthode clearProductLines, et pourtant ton test est toujours vert ! Bravo la qualité !”

Allez encore 319 !

Ça risque d’être trop long on va pas tous les faire. Quoique…Cliquez ici.

L’intérêt d’Infection est donc là, il vous montre les endroits de votre code qui ne sont pas testés, même si la couverture de code vous dit que oui.

En effet PHPUnit peut vous montrer une ligne de code verte, par exemple:

Typiquement la couverture de code existe, mais Infection va générer des mutants, il va créer :

Si vous travaillez avec des nombres à virgules comme 0.005 que vous multipliez ou divisez par 10 ça sera toujours inférieur à 1.5 !

Bon vous allez me dire “super l’intérêt de ce mutant ! je compte pas changer le calcul”.

Après c’est à vous de voir…Si vous êtes seul sur le projet, il y a peu de chance d’aller modifier ce code. Si vous êtes plusieurs, le risque existe. Et si une autre personne reprends le projet et qu’elle modifie le code et qu’elle ne voit pas d’erreur, ça peut être difficile de retrouver le problème.

Metrics

Infection met à disposition des metrics, des scores, pour suivre l’évolution des mutants.

Mutation Score Indicator (MSI)

Plus le MSI est élevé et plus vous avez vaincu de mutants !

Si on refait le calcul :
(626 + 0 + 3) / 1201 = 0.52 * 100 = 52%

Mutation Code Coverage

Correspond au pourcentage de mutants couvert par votre code.

On retire SommeDesMutantsNonCouvertParLesTests du calcul parce qu’Infection génère des mutants pour tous vos tests, même aux endroits non testés.

Si on refait le calcul :
(1201 – 321) / 1201 = 0.73 * 100 = 73%

Covered Code Mutation Score Indicator

Corresponds au pourcentage de mutants vaincus par rapport à vos tests. C’est cet indicateur qui nous permet de savoir si on a écrit des tests efficaces !

Si on refait le calcul :
(626 + 0 + 3) / (1201 – 321) = 0.71 * 100 = 71%

Résumons les metrics

  • MSI : Nous donne le pourcentage de mutants vaincus par rapport au nombre total (couvert ou non couvert par vos tests) de mutants générés.
  • MCC : Nous donne le pourcentage de mutants créés sur votre couverture de code par rapport au nombre total de mutants créés. Normalement ce pourcentage devrait être sensiblement le même que la couverture de code classique de PHPUnit.
  • CoveredMSI : Nous donne le pourcentage de mutants vaincus par rapport au nombre de mutants créés sur votre couverture de code.

MSI et CoveredMSI sont deux indicateurs intéressants.

Le premier nous dit qu’il y a 52% de mutants vaincus au total. Et le second nous dit qu’il y a en fait 71% de mutants vaincus par rapport à vos tests. C’est pas si mal !

C’est maintenant qu’arrive le meilleur !

Grâce à Infection, vous allez pouvoir améliorer la qualité de vos projets et de vos tests :

  • Vous allez vous mettre à écrire plus de tests pour tuer des mutants
  • Vous allez pouvoir mettre en place des défenses sur vos features/PR/MR.

En effet, Infection met à disposition deux options en ligne de commande :

  1. –min-msi : La valeur minimale du MSI. Ça signifit que si vous ajoutez beaucoup de code mais pas de tests, votre MSI va chuter et votre build va “failed”.
  2. –min-covered-msi: La valeur minimale du CoveredMSI. Ça signifit que si vous ajoutez beaucoup de code, et beaucoup de tests, ça ne voudra pas dire pour autant que vos tests seront efficaces et tueront du mutants !

Pour chacune des options, Infection vous suggérera en cas de “success” d’augmenter les valeurs minimales, de manière à continuer vos efforts toujours plus haut !

Maintenant vous n’avez plus d’excuses pour ne pas écrire de tests.

Important

C’est important de respecter les gestes barrières avec tous ces mutants.

Voir l’étude de cas
Lire l’article
Voir le témoignage
Fermer