Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Débusquez les failles cachées : Maîtrisez vos t...

Débusquez les failles cachées : Maîtrisez vos tests PHP avec PHPInfection & Pest

🇬🇧 🇺🇸 English version below

🇫🇷 French version

Talk donné à la conférence AFUP Day Lyon 2025

Plongeons ensemble dans l'univers des tests de mutations et découvrons comment ils exposent les failles invisibles de notre code.

Grâce à l'outil de mutation testing PHPInfection et au framework de test moderne Pest, nous verrons comment nous pouvons renforcer nos tests unitaires pour qu’ils résistent aux erreurs les plus subtiles.

Ensemble, nous relèverons le défi de détecter les bugs cachés et d'améliorer la robustesse de nos projets PHP !

--------------------------------------------

🇬🇧 🇺🇸 English version

Talk at the AFUP Day Lyon 2025 conference

For the English version of this talk, consider the following English conference version:
Slides for Symfony Online June 2025

Let's dive into the world of mutation testing and discover how it exposes invisible flaws in our code.

ÂUsing the PHPInfection mutation testing tool with PHPUnit and the Pest testing framework, we'll see how we can strengthen our unit tests to resist the most subtle errors.

Together, we'll take up the challenge of detecting hidden bugs and improving the robustness of our PHP projects.

Avatar for Vincent Amstoutz

Vincent Amstoutz

June 03, 2025
Tweet

More Decks by Vincent Amstoutz

Other Decks in Programming

Transcript

  1. Débusquez les failles cachées Maîtrisez vos tests PHP avec Infection

    & Pest Photo by CDC on Unsplash © Vincent AMSTOUTZ
  2. Vincent Amstoutz ➔ Coopérateur senior dev – Les-Tilleuls.coop ➔ Contributeur

    OSS ➔ Lectures techs & inspiration ➔ Fada de sport et de musique @vinceAmstoutz Photo by Ben Griffiths on Unsplash @vincent-amstoutz
  3. 70+ experts en API, Web et Cloud ➔ Développement :

    PHP, JS, Go, Rust… ➔ DevOps et Cloud ➔ Consulting et audits ➔ Formations ➔ [email protected] 💌 © Vincent AMSTOUTZ
  4. Usage des tests ± 50% DES PROJETS EN ENTREPRISE ±

    90% DES PROJETS OSS RECONNUS ± 30% DES PROJETS PERSONNELS ET SCOLAIRES © Vincent AMSTOUTZ Graphe simplifié - Source: blog.jetbrains.com Source: gartener.com
  5. © Vincent AMSTOUTZ Les tests, utiles ? "Le refactor est

    quelque chose que vous faites pour garder votre code sain, tandis que les tests sont là pour vous dire si vous avez cassé quelque chose." – Martin Fowler "Un code sans tests n'est pas propre. Aussi élégant soit-il, aussi lisible et accessible soit-il, s'il n'est pas testé, il n’est pas propre." – Robert C. Martin aka Uncle Bob
  6. © Vincent AMSTOUTZ Un game changer, vraiment ? SANS TESTS

    (3j après…) AVEC TESTS © Vincent AMSTOUTZ
  7. © Vincent AMSTOUTZ ↩ Les migrations et les évolutions techniques

    🆕 Les évolutions fonctionnelles Les évolutions d’usage Un atout indispensable pour 📊
  8. © Vincent AMSTOUTZ 🧪 Tests efficients ? Pourquoi évaluer les

    tests ? 📊 Couvrent quelles parties du projet ?
  9. © Vincent AMSTOUTZ Les tests de mutation ! 🎉 Tests

    Code exécuté Tests de mutation vérifient la “qualité” des… vérifient la “qualité” du…
  10. © Vincent AMSTOUTZ Le mutant 🕷 "Le MT consiste à

    modifier un programme par petites touches. Chaque version mutée est appelée mutant”. – Infection
  11. © Vincent AMSTOUTZ Notre 1er mutant 🕷 {...} public function

    addition(float $a, float $b): float { - return $a + $b; + return $a - $b; } © Vincent AMSTOUTZ Inversion d’un opérateur
  12. © Vincent AMSTOUTZ Mutations Le mutation testing 🕷 Code source

    Mutant Mutant Mutant Mutant Infection / Pest Tests Liste de mutateurs 1/ Analyse (via l’AST) 2/ Génère des modifications 3/ Lance les tests avec les mutations Résultat
  13. © Vincent AMSTOUTZ Notre 1er mutant 🕷 public function addition(float

    $a, float $b): float { - return $a + $b; + return $a - $b; } © Vincent AMSTOUTZ Mutant échappé public function testAddition(): void { $result = $this->addition(2, 0); self::assertSame(2, $result); }
  14. © Vincent AMSTOUTZ Autre mutant 🕷 public function addition(float $a,

    float $b): float { - return $a + $b; + return $a / $b; } © Vincent AMSTOUTZ Mutant détecté
  15. © Vincent AMSTOUTZ Pré-requis ⚠ Nécessite un driver pour le

    coverage (extension PHP à installer) Pro tip : activez le coverage dans la config PHP de dev & test XDEBUG_MODE=coverage; pecl install pcov
  16. © Vincent AMSTOUTZ ➔ PHPUnit ➔ PhpSpec ➔ Codeception Choix

    de la librairie de tests Infection supporte ⬅ pour cette conf’
  17. © Vincent AMSTOUTZ Installation d’Infection { "logs": { "text": "./infection/infection.log",

    "html": "./infection/infection.html", "summary": "./infection/summary.log", "perMutator": "./infection/per-mutator.md", }, "mutators": { "@default": true }, } © Vincent AMSTOUTZ composer require --working-dir=tools/infection infection/infection
  18. © Vincent AMSTOUTZ final class UserAdultFilterAge { public function __invoke(array

    $users): array { return array_filter( $users, fn (User $user) => $user->age >= 18, ); } } © Vincent AMSTOUTZ
  19. © Vincent AMSTOUTZ {...} final class UserAdultFilterAgeTest extends TestCase {

    {...} public function test_it_filters_adults(): void { $filter = new UserAdultFilterAge(); $users = [ new User(“Tom”,age: 20), new User(“Alicia”, age: 15), ]; self::assertCount(1, $filter($users)); } } © Vincent AMSTOUTZ
  20. © Vincent AMSTOUTZ Avec correction public function test_it_filters_adults(): void {

    $filter = new UserAdultFilterAge(); $users = [ new User(“Tom”, age: 20), new User(“Alicia”, age: 15), new User(“Matéo”, age: 18), ]; self::assertCount(2, $filter($users)); } © Vincent AMSTOUTZ
  21. © Vincent AMSTOUTZ Configuration de Pest Se base sur la

    configuration PHPUnit ➔ La plupart des options sont via la CLI ➔ Fichier de config Pest.php (peu d’options fournies)
  22. © Vincent AMSTOUTZ Tests non requis pour Pest Capable de

    détecter du code non testé pest --mutate --everything
  23. © Vincent AMSTOUTZ {...} final readonly class IsEven { public

    function __invoke(int $number): bool { return $number % 2 === 0; } } © Vincent AMSTOUTZ {...} it('returns true for even numbers', function () { expect(new IsEven()(2))->toBeTrue(); });
  24. © Vincent AMSTOUTZ © Vincent AMSTOUTZ {...} it('returns true for

    even numbers', function () { expect(new IsEven()(2))->toBeTrue(); }); it('returns false for odd numbers', function () { expect(new IsEven()(3))->toBeFalse(); }); Avec correction
  25. Infection VS Pest Avantages ➔ Indépendant et framework agnostique ➔

    Nombre plus important de mutateurs ➔ Permet la création de mutants Inconvénients ➔ Version 0.* depuis 2017 Avantages ➔ Peut détecter des tests manquants ➔ Inclus des outils de tests supplémentaires Inconvénients ➔ Moins de mutateurs qu’Infection ➔ Pas de mutants spécifiques à Symfony ➔ Roadmap orienté vers un framework VS © Vincent AMSTOUTZ
  26. © Vincent AMSTOUTZ Intégrer sur un projet existant Projet sans

    tests Apprendre à écrire des tests Ajouter des tests au fur et à mesure
  27. © Vincent AMSTOUTZ Intégrer sur un projet existant 1/ Consolider

    le code couvert par les tests ./vendor/bin/pest --mutate --covered-only --parallel infection --only-covered --threads=max Projet avec tests
  28. © Vincent AMSTOUTZ Intégrer sur un projet existant 1/ Consolider

    le code couvert par les tests 2/ Ajouter à la CI ./vendor/bin/pest --mutate --min=90 --parallel --covered-only infection --min-covered-msi=90 --threads=max Projet avec tests
  29. © Vincent AMSTOUTZ Intégrer sur un projet existant 1/ Consolider

    le code couvert par les tests 2/ Ajouter à la CI 3/ Consolider la couverture des tests Projet avec tests
  30. © Vincent AMSTOUTZ Intégrer sur un projet existant 1/ Consolider

    le code couvert par les tests 2/ Ajouter à la CI 3/ Augmenter la couverture des tests 4/ Ajuster dans la CI les pré-requis ./vendor/bin/pest --mutate --min=100 --parallel --covered-only infection --min-covered-msi=100 --threads=max Projet avec tests
  31. © Vincent AMSTOUTZ En savoir + sur les tests 👩󰘃

    ➔ https://fr.linkedin.com/in/pierre-criulanscy 󰏃 ➔ https://fr.linkedin.com/in/michael-azerhad 󰏃 ➔ https://fr.linkedin.com/in/anthony-cyrille 󰏃 ➔ https://fr.linkedin.com/in/valentinajemuovic 󰏅 📚 ➔ Software Craft - TDD, Clean Code & other essential practices By C. Martaire, A. Thiéfaine, D. Bartaguiz, F. Hiegel & H. Fakiih 󰏃 ➔ Clean Code: A Handbook of Agile Software Craftsmanship By Robert C. Martin 󰏅
  32. Merci de votre attention ! ➔ Des questions ? Avis

    appréciés ! 󰚦 @vincent-amstoutz @vinceAmstoutz