Infection : le framework de mutation testing pour PHP

24 septembre 2025 3 min
La couverture de code n’est pas toujours gage de qualité : on peut atteindre 100 % sans avoir de vrais tests. Avec Infection, framework de mutation testing pour PHP, vos tests sont mis à l’épreuve grâce à la génération de mutants. Résultat : une suite de tests plus fiable et une meilleure qualité logicielle.

Nous savons tous que les tests unitaires permettent de vérifier que le code fonctionne comme prévu. Une des métriques les plus utilisées est la couverture de code. Mais peut-on réellement s’y fier ? En réalité, il est possible d’atteindre 100 % de couverture tout en ayant des tests inutiles… Par exemple, remplacer toutes les assertions par assertSame(1, 1) donnera un score parfait, mais ne validera rien du tout.

Alors, comment mesurer la qualité réelle de vos tests ? La réponse se trouve dans le mutation testing.

Qu’est-ce que le mutation testing ?

Le mutation testing consiste à modifier légèrement le code source pour créer des mutants et à analyser la réaction de la suite de tests.

  • Si les tests échouent, le mutant est « tué » (c’est positif).
  • Si les tests passent, le mutant « survit » : cela signifie que le code n’est pas couvert ou que les tests sont inefficaces.

Ces modifications sont appelées mutateurs : inversion de conditions, changement de valeurs de retour, modification de la visibilité d’une méthode, etc.

Le processus est précis et reproductible, et non pas aléatoire.

Exemple avec Infection pour PHP

Prenons un filtre qui exclut les utilisateurs de moins de 18 ans. Un test unitaire basique permet d’obtenir 100 % de couverture de code. Pourtant, en lançant Infection :

./infection.phar --threads=4

on constate que le Mutation Score Indicator (MSI) n’est que de 47 %. Autrement dit, plus de la moitié des mutants générés ne sont pas détectés.

Les métriques clés :

  • MSI (Mutation Score Indicator) : pourcentage de mutants tués, indicateur principal de qualité.
  • Mutation Code Coverage : pourcentage de mutants effectivement couverts par des tests.
  • Covered Code MSI : efficacité des tests uniquement sur le code couvert.

Dans l’exemple, bien que la couverture affichait 65 %, l’efficacité réelle était bien plus faible.

Améliorer ses tests grâce aux mutants

  • En ajoutant un test de valeur limite (18 ans), un mutant jusque-là survivant est éliminé.
  • En ajoutant un typehint de retour à une méthode, certains mutants ne sont même plus générés.

Ainsi, Infection force à écrire des tests plus précis et robustes, et permet d’obtenir à la fois 100 % de couverture et 100 % de mutation coverage, une mesure bien plus fiable.

Mutateurs avancés

Infection va plus loin avec des mutateurs comme :

  • PublicVisibility et ProtectedVisibility : pour vérifier que la visibilité d’une méthode est justifiée.
  • Gestion des timeouts : par exemple, un ++ remplacé par -- peut provoquer une boucle infinie. Infection détecte ce cas et le marque comme « Timeout » (considéré positif).

Installation et configuration

  • Infection nécessite PHP 7.0+ avec xDebug ou phpdbg.
  • Il est conseillé de l’utiliser en distribution PHAR pour éviter les conflits de dépendances : ./infection.phar self-update
  • Compatible avec PHPUnit (5, 6+) et PHPSpec.
  • Au premier lancement, un fichier infection.json.dist est généré et peut être versionné pour l’intégration CI.

Options utiles

  • --threads : exécuter les tests mutants en parallèle.
  • --show-mutations : afficher les diffs colorés des mutations.
  • --mutators : choisir un ensemble précis de mutateurs.
  • --min-msi et --min-covered-msi : fixer des seuils minimaux dans un pipeline CI pour garantir la qualité des tests.

Exemple avec Travis CI :

before_script:
  - wget <https://github.com/infection/infection/releases/download/0.6.0/infection.phar>
  - wget <https://github.com/infection/infection/releases/download/0.6.0/infection.phar.pubkey>
  - chmod +x infection.phar
script:
  - ./infection.phar --min-covered-msi=90 --threads=4

Utilisation au quotidien

  • Pour un développeur : écrire une nouvelle classe, la tester, puis lancer Infection uniquement sur ce fichier pour vérifier l’efficacité des tests.
  • Pour un projet : intégrer Infection dans la CI afin d’analyser régulièrement les logs et de maintenir un niveau élevé de MSI.

À noter : atteindre 100 % MSI n’est pas toujours possible. Certains mutants dits équivalents (par ex. multiplier par ±1) ne changent pas réellement le comportement du code et ne peuvent donc pas être tués.

Mutation testing et AST

Infection repose sur l’Abstract Syntax Tree (AST) pour analyser et muter le code de manière structurée, bien plus fiable que l’approche par simples tokens. Grâce à l’AST :

  • L’ajout de nouveaux mutateurs est plus simple.
  • Les faux positifs sont réduits.
  • Le code est plus facile à maintenir.

Conclusion

Le mutation testing est une méthode puissante pour améliorer la qualité d’une suite de tests.

Avec Infection, les développeurs PHP disposent d’un outil efficace pour aller au-delà de la couverture de code et écrire des tests réellement utiles.

Merci de votre lecture 😎

Ecrit par
Alyson Paya

Partager l'article :

Vous avez un projet ?

Un site vitrine ? e-commerce ? une application ?

Contactez-nous

Découvrez les derniers articles

Tout voir