SlideShare a Scribd company logo

Mutation testing, enfin une bonne mesure de la qualité des tests ?, RivieraDev le 18/05/2018

On écrit tous des tests (n’est-ce pas ?), mais comment savoir s’ils sont utiles ? - Par leur nombre ? Faux, beaucoup de tests ne garantissent pas que l’application fonctionne correctement - Avec une bonne couverture du code ? Encore faux, mieux mais pas suffisant L’important est d'être confiant sur la capacité des tests à détecter les problèmes (c’est pourquoi en TDD un test doit échouer au début, pour etre sur qu’il teste bien quelque chose). Laissez-moi donc vous présenter le mutation testing ! Cette technique modifie votre code, lance les tests et s’attend à ce qu’ils échouent. Si non, c’est que cette partie est mal testée… Dans ce talk je détaillerai les principes du mutation testing, expliquerai comment l’utiliser sur un projet scala et montrerai les résultats obtenus sur un projet réel.

1 of 43
Download to read offline
Mutation testing
Gotta Kill ’Em All !
Loïc Knuchel
Loïc Knuchel@loicknuchel
Développeur Scala chez
Organisateur des Paris
Software craftsman
loicknuchel@gmail.com
DDD
FP
CQRS
Hexagonal architecture
Property based testing
Event Sourcing
Event Storming
TDD
Living documentation
Loïc Knuchel - @loicknuchel
● Peu de bugs
● Lisible par un autre
développeur
● Pas trop dur à faire
évoluer
Loïc Knuchel - @loicknuchel
Loïc Knuchel - @loicknuchel
Stratégies de test
Loïc Knuchel - @loicknuchel
Du code
robuste grâce
aux tests
Ad

Recommended

More Related Content

Similar to Mutation testing, enfin une bonne mesure de la qualité des tests ?, RivieraDev le 18/05/2018

Formation Gratuite Total Tests par les experts Java Ippon
Formation Gratuite Total Tests par les experts Java Ippon Formation Gratuite Total Tests par les experts Java Ippon
Formation Gratuite Total Tests par les experts Java Ippon Ippon
 
Infra as Code, choisissez vous la pilule rouge ou la pilule bleue - Devoxx 2016
Infra as Code, choisissez vous la pilule rouge ou la pilule bleue - Devoxx 2016Infra as Code, choisissez vous la pilule rouge ou la pilule bleue - Devoxx 2016
Infra as Code, choisissez vous la pilule rouge ou la pilule bleue - Devoxx 2016Fabien Arcellier
 
testUnitaire (1).pptx
testUnitaire (1).pptxtestUnitaire (1).pptx
testUnitaire (1).pptxManalAg
 
Tester unitairement une application java
Tester unitairement une application javaTester unitairement une application java
Tester unitairement une application javaAntoine Rey
 
Integration continue - Introduction
Integration continue - IntroductionIntegration continue - Introduction
Integration continue - IntroductionOlivier ETIENNE
 
PHPTour Lyon 2014 - Conférence - Tests unitaires Je veux mes 80% de couvertur...
PHPTour Lyon 2014 - Conférence - Tests unitaires Je veux mes 80% de couvertur...PHPTour Lyon 2014 - Conférence - Tests unitaires Je veux mes 80% de couvertur...
PHPTour Lyon 2014 - Conférence - Tests unitaires Je veux mes 80% de couvertur...Cyrille Grandval
 
Les générateurs de code, pour se simplifier la vie au quotidien
Les générateurs de code, pour se simplifier la vie au quotidienLes générateurs de code, pour se simplifier la vie au quotidien
Les générateurs de code, pour se simplifier la vie au quotidienNicolas Carlo
 
l'Industrialisation (avec PHP) @MMIConnect
l'Industrialisation (avec PHP) @MMIConnectl'Industrialisation (avec PHP) @MMIConnect
l'Industrialisation (avec PHP) @MMIConnectFlorent DENIS
 
Automatisation des tests - objectifs et concepts - partie 2
Automatisation des tests  - objectifs et concepts - partie 2Automatisation des tests  - objectifs et concepts - partie 2
Automatisation des tests - objectifs et concepts - partie 2Christophe Rochefolle
 
Automatisation des tests - objectifs et concepts - partie 1
Automatisation des tests  - objectifs et concepts - partie 1Automatisation des tests  - objectifs et concepts - partie 1
Automatisation des tests - objectifs et concepts - partie 1Christophe Rochefolle
 
Plpython et Triggers
Plpython et TriggersPlpython et Triggers
Plpython et TriggersAffinitic
 
Design Pattern introduction
Design Pattern introductionDesign Pattern introduction
Design Pattern introductionneuros
 
Cracking RSA key - Quantum Computing - #GlobalAzure Bootcamp - Louis Charavne...
Cracking RSA key - Quantum Computing - #GlobalAzure Bootcamp - Louis Charavne...Cracking RSA key - Quantum Computing - #GlobalAzure Bootcamp - Louis Charavne...
Cracking RSA key - Quantum Computing - #GlobalAzure Bootcamp - Louis Charavne...FactoVia
 
Plop : un micro-générateur pour se simplifier la vie au quotidien
Plop : un micro-générateur pour se simplifier la vie au quotidienPlop : un micro-générateur pour se simplifier la vie au quotidien
Plop : un micro-générateur pour se simplifier la vie au quotidienNicolas Carlo
 
Industrialiser le contrat dans un projet PHP
Industrialiser le contrat dans un projet PHPIndustrialiser le contrat dans un projet PHP
Industrialiser le contrat dans un projet PHPhalleck45
 
PyConFR - testons en python
PyConFR - testons en pythonPyConFR - testons en python
PyConFR - testons en pythongburet
 
Python For Data Science - French Course
Python For Data Science - French CoursePython For Data Science - French Course
Python For Data Science - French CourseHaytam EL YOUSSFI
 

Similar to Mutation testing, enfin une bonne mesure de la qualité des tests ?, RivieraDev le 18/05/2018 (20)

Formation Gratuite Total Tests par les experts Java Ippon
Formation Gratuite Total Tests par les experts Java Ippon Formation Gratuite Total Tests par les experts Java Ippon
Formation Gratuite Total Tests par les experts Java Ippon
 
Infra as Code, choisissez vous la pilule rouge ou la pilule bleue - Devoxx 2016
Infra as Code, choisissez vous la pilule rouge ou la pilule bleue - Devoxx 2016Infra as Code, choisissez vous la pilule rouge ou la pilule bleue - Devoxx 2016
Infra as Code, choisissez vous la pilule rouge ou la pilule bleue - Devoxx 2016
 
Bbl sur les tests
Bbl sur les testsBbl sur les tests
Bbl sur les tests
 
testUnitaire (1).pptx
testUnitaire (1).pptxtestUnitaire (1).pptx
testUnitaire (1).pptx
 
Tester unitairement une application java
Tester unitairement une application javaTester unitairement une application java
Tester unitairement une application java
 
Integration continue - Introduction
Integration continue - IntroductionIntegration continue - Introduction
Integration continue - Introduction
 
PHPTour Lyon 2014 - Conférence - Tests unitaires Je veux mes 80% de couvertur...
PHPTour Lyon 2014 - Conférence - Tests unitaires Je veux mes 80% de couvertur...PHPTour Lyon 2014 - Conférence - Tests unitaires Je veux mes 80% de couvertur...
PHPTour Lyon 2014 - Conférence - Tests unitaires Je veux mes 80% de couvertur...
 
Les générateurs de code, pour se simplifier la vie au quotidien
Les générateurs de code, pour se simplifier la vie au quotidienLes générateurs de code, pour se simplifier la vie au quotidien
Les générateurs de code, pour se simplifier la vie au quotidien
 
l'Industrialisation (avec PHP) @MMIConnect
l'Industrialisation (avec PHP) @MMIConnectl'Industrialisation (avec PHP) @MMIConnect
l'Industrialisation (avec PHP) @MMIConnect
 
Automatisation des tests - objectifs et concepts - partie 2
Automatisation des tests  - objectifs et concepts - partie 2Automatisation des tests  - objectifs et concepts - partie 2
Automatisation des tests - objectifs et concepts - partie 2
 
Automatisation des tests - objectifs et concepts - partie 1
Automatisation des tests  - objectifs et concepts - partie 1Automatisation des tests  - objectifs et concepts - partie 1
Automatisation des tests - objectifs et concepts - partie 1
 
Plpython et Triggers
Plpython et TriggersPlpython et Triggers
Plpython et Triggers
 
Design Pattern introduction
Design Pattern introductionDesign Pattern introduction
Design Pattern introduction
 
Cracking RSA key - Quantum Computing - #GlobalAzure Bootcamp - Louis Charavne...
Cracking RSA key - Quantum Computing - #GlobalAzure Bootcamp - Louis Charavne...Cracking RSA key - Quantum Computing - #GlobalAzure Bootcamp - Louis Charavne...
Cracking RSA key - Quantum Computing - #GlobalAzure Bootcamp - Louis Charavne...
 
Des tests modernes pour Drupal
Des tests modernes pour DrupalDes tests modernes pour Drupal
Des tests modernes pour Drupal
 
Tour d'horizon des tests
Tour d'horizon des testsTour d'horizon des tests
Tour d'horizon des tests
 
Plop : un micro-générateur pour se simplifier la vie au quotidien
Plop : un micro-générateur pour se simplifier la vie au quotidienPlop : un micro-générateur pour se simplifier la vie au quotidien
Plop : un micro-générateur pour se simplifier la vie au quotidien
 
Industrialiser le contrat dans un projet PHP
Industrialiser le contrat dans un projet PHPIndustrialiser le contrat dans un projet PHP
Industrialiser le contrat dans un projet PHP
 
PyConFR - testons en python
PyConFR - testons en pythonPyConFR - testons en python
PyConFR - testons en python
 
Python For Data Science - French Course
Python For Data Science - French CoursePython For Data Science - French Course
Python For Data Science - French Course
 

More from Loïc Knuchel

Scala bad practices, scala.io 2019
Scala bad practices, scala.io 2019Scala bad practices, scala.io 2019
Scala bad practices, scala.io 2019Loïc Knuchel
 
Comprendre la programmation fonctionnelle, Blend Web Mix le 02/11/2016
Comprendre la programmation fonctionnelle, Blend Web Mix le 02/11/2016Comprendre la programmation fonctionnelle, Blend Web Mix le 02/11/2016
Comprendre la programmation fonctionnelle, Blend Web Mix le 02/11/2016Loïc Knuchel
 
Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016Loïc Knuchel
 
Ionic2 - the raise of web developer, Riviera DEV le 17/06/2016
Ionic2 - the raise of web developer, Riviera DEV le 17/06/2016Ionic2 - the raise of web developer, Riviera DEV le 17/06/2016
Ionic2 - the raise of web developer, Riviera DEV le 17/06/2016Loïc Knuchel
 
FP is coming... le 19/05/2016
FP is coming... le 19/05/2016FP is coming... le 19/05/2016
FP is coming... le 19/05/2016Loïc Knuchel
 
Programmation fonctionnelle en JavaScript
Programmation fonctionnelle en JavaScriptProgrammation fonctionnelle en JavaScript
Programmation fonctionnelle en JavaScriptLoïc Knuchel
 
Ionic Framework, L'avenir du mobile sera hybride, bdx.io le 16-10-2015
Ionic Framework, L'avenir du mobile sera hybride, bdx.io le 16-10-2015Ionic Framework, L'avenir du mobile sera hybride, bdx.io le 16-10-2015
Ionic Framework, L'avenir du mobile sera hybride, bdx.io le 16-10-2015Loïc Knuchel
 
Ionic, ce n'est pas que de l'UI, meetup PhoneGap le 25-05-2015
Ionic, ce n'est pas que de l'UI, meetup PhoneGap le 25-05-2015Ionic, ce n'est pas que de l'UI, meetup PhoneGap le 25-05-2015
Ionic, ce n'est pas que de l'UI, meetup PhoneGap le 25-05-2015Loïc Knuchel
 
Le développement mobile hybride sort du bois, Ch'ti JUG le 15-04-2015
Le développement mobile hybride sort du bois, Ch'ti JUG le 15-04-2015Le développement mobile hybride sort du bois, Ch'ti JUG le 15-04-2015
Le développement mobile hybride sort du bois, Ch'ti JUG le 15-04-2015Loïc Knuchel
 
Devoxx 2015, Atelier Ionic - 09/04/2015
Devoxx 2015, Atelier Ionic - 09/04/2015Devoxx 2015, Atelier Ionic - 09/04/2015
Devoxx 2015, Atelier Ionic - 09/04/2015Loïc Knuchel
 
Devoxx 2015, ionic chat
Devoxx 2015, ionic chatDevoxx 2015, ionic chat
Devoxx 2015, ionic chatLoïc Knuchel
 
Ionic HumanTalks - 11/03/2015
Ionic HumanTalks - 11/03/2015Ionic HumanTalks - 11/03/2015
Ionic HumanTalks - 11/03/2015Loïc Knuchel
 
Ionic bbl le 19 février 2015
Ionic bbl le 19 février 2015Ionic bbl le 19 février 2015
Ionic bbl le 19 février 2015Loïc Knuchel
 
Des maths et des recommandations - Devoxx 2014
Des maths et des recommandations - Devoxx 2014Des maths et des recommandations - Devoxx 2014
Des maths et des recommandations - Devoxx 2014Loïc Knuchel
 

More from Loïc Knuchel (14)

Scala bad practices, scala.io 2019
Scala bad practices, scala.io 2019Scala bad practices, scala.io 2019
Scala bad practices, scala.io 2019
 
Comprendre la programmation fonctionnelle, Blend Web Mix le 02/11/2016
Comprendre la programmation fonctionnelle, Blend Web Mix le 02/11/2016Comprendre la programmation fonctionnelle, Blend Web Mix le 02/11/2016
Comprendre la programmation fonctionnelle, Blend Web Mix le 02/11/2016
 
Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
Ionic2, les développeurs web à l'assaut du mobile, BDX I/O le 21/10/2016
 
Ionic2 - the raise of web developer, Riviera DEV le 17/06/2016
Ionic2 - the raise of web developer, Riviera DEV le 17/06/2016Ionic2 - the raise of web developer, Riviera DEV le 17/06/2016
Ionic2 - the raise of web developer, Riviera DEV le 17/06/2016
 
FP is coming... le 19/05/2016
FP is coming... le 19/05/2016FP is coming... le 19/05/2016
FP is coming... le 19/05/2016
 
Programmation fonctionnelle en JavaScript
Programmation fonctionnelle en JavaScriptProgrammation fonctionnelle en JavaScript
Programmation fonctionnelle en JavaScript
 
Ionic Framework, L'avenir du mobile sera hybride, bdx.io le 16-10-2015
Ionic Framework, L'avenir du mobile sera hybride, bdx.io le 16-10-2015Ionic Framework, L'avenir du mobile sera hybride, bdx.io le 16-10-2015
Ionic Framework, L'avenir du mobile sera hybride, bdx.io le 16-10-2015
 
Ionic, ce n'est pas que de l'UI, meetup PhoneGap le 25-05-2015
Ionic, ce n'est pas que de l'UI, meetup PhoneGap le 25-05-2015Ionic, ce n'est pas que de l'UI, meetup PhoneGap le 25-05-2015
Ionic, ce n'est pas que de l'UI, meetup PhoneGap le 25-05-2015
 
Le développement mobile hybride sort du bois, Ch'ti JUG le 15-04-2015
Le développement mobile hybride sort du bois, Ch'ti JUG le 15-04-2015Le développement mobile hybride sort du bois, Ch'ti JUG le 15-04-2015
Le développement mobile hybride sort du bois, Ch'ti JUG le 15-04-2015
 
Devoxx 2015, Atelier Ionic - 09/04/2015
Devoxx 2015, Atelier Ionic - 09/04/2015Devoxx 2015, Atelier Ionic - 09/04/2015
Devoxx 2015, Atelier Ionic - 09/04/2015
 
Devoxx 2015, ionic chat
Devoxx 2015, ionic chatDevoxx 2015, ionic chat
Devoxx 2015, ionic chat
 
Ionic HumanTalks - 11/03/2015
Ionic HumanTalks - 11/03/2015Ionic HumanTalks - 11/03/2015
Ionic HumanTalks - 11/03/2015
 
Ionic bbl le 19 février 2015
Ionic bbl le 19 février 2015Ionic bbl le 19 février 2015
Ionic bbl le 19 février 2015
 
Des maths et des recommandations - Devoxx 2014
Des maths et des recommandations - Devoxx 2014Des maths et des recommandations - Devoxx 2014
Des maths et des recommandations - Devoxx 2014
 

Mutation testing, enfin une bonne mesure de la qualité des tests ?, RivieraDev le 18/05/2018

  • 1. Mutation testing Gotta Kill ’Em All ! Loïc Knuchel
  • 2. Loïc Knuchel@loicknuchel Développeur Scala chez Organisateur des Paris Software craftsman loicknuchel@gmail.com DDD FP CQRS Hexagonal architecture Property based testing Event Sourcing Event Storming TDD Living documentation
  • 3. Loïc Knuchel - @loicknuchel ● Peu de bugs ● Lisible par un autre développeur ● Pas trop dur à faire évoluer
  • 4. Loïc Knuchel - @loicknuchel
  • 5. Loïc Knuchel - @loicknuchel Stratégies de test
  • 6. Loïc Knuchel - @loicknuchel Du code robuste grâce aux tests
  • 7. Loïc Knuchel - @loicknuchel Tester les tests
  • 8. Loïc Knuchel - @loicknuchel Etape 1: l’intuition
  • 9. Loïc Knuchel - @loicknuchel Etape 2: couverture de code
  • 10. Loïc Knuchel - @loicknuchel Solution 2: couverture de code
  • 11. Loïc Knuchel - @loicknuchel Code exécuté par des tests != code testé class Cart(size: Int) { val items = mutable.ArrayBuffer[String]() def add(item: String): Boolean = { println(s"item add: $item") val exists = items.contains(item) if(items.length < size) { items.append(item) } exists } } it("has no assert") { new Cart(3).add("shoes") }
  • 12. Loïc Knuchel - @loicknuchel Code exécuté par des tests != code testé it("has irrelevant assert") { new Cart(3).add("shoes") shouldBe false } class Cart(size: Int) { val items = mutable.ArrayBuffer[String]() def add(item: String): Boolean = { println(s"item add: $item") val exists = items.contains(item) if(items.length < size) { items.append(item) } exists } }
  • 13. Loïc Knuchel - @loicknuchel Code exécuté par des tests != code testé class Cart(size: Int) { val items = mutable.ArrayBuffer[String]() def add(item: String): Boolean = { println(s"item add: $item") val exists = items.contains(item) if(items.length < size) { items.append(item) } exists } } Non testé : ● les effets de bords ● la condition limite ● l’ajout dans la liste it("asserts few things") { val cart = new Cart(3) cart.add("shoes") cart.items.length shouldBe 1 }
  • 14. Loïc Knuchel - @loicknuchel Code exécuté par des tests != code testé
  • 15. Loïc Knuchel - @loicknuchel Tout le code ne se vaut pas
  • 16. Loïc Knuchel - @loicknuchel Etape 3 Mutation testing
  • 17. Loïc Knuchel - @loicknuchel Mise en place: Java // pom.xml <build> <plugins> <plugin> <groupId>org.pitest</groupId> <artifactId>pitest-maven</artifactId> <version>1.2.4</version> </plugin> </plugins> </build> $ mvn org.pitest:pitest-maven:mutationCoverage
  • 18. Loïc Knuchel - @loicknuchel Mise en place: Scala // project/plugins.sbt addSbtPlugin("io.github.sugakandrey" % "sbt-scalamu" % "0.1.1") $ sbt mutationTest Scalamu
  • 19. Loïc Knuchel - @loicknuchel Mise en place: JavaScript $ ./node_modules/.bin/stryker run // stryker.conf.js module.exports = function(config) { config.set({ testRunner: "jest", mutator: "javascript", transpilers: [], reporter: ["html", "progress"], coverageAnalysis: "all", mutate: ["src/**/*.js"] }); }; $ npm install stryker stryker-api stryker-html-reporter stryker-javascript-mutator stryker-jest-runner --save- dev Stryker
  • 20. Loïc Knuchel - @loicknuchel Et plein d’autres... NinjaTurtles pour C# Mutmut pour Python mutant pour Ruby Infection pour PHP ...
  • 21. Loïc Knuchel - @loicknuchel Mutation testing
  • 22. Loïc Knuchel - @loicknuchel Génère un mutant Lance les tests Vérifie le résultat Recommence
  • 23. Loïc Knuchel - @loicknuchel Mutant tué Si les tests échouent Le code muté a été détecté Il est donc correctement testé
  • 24. Loïc Knuchel - @loicknuchel Mutant vivant Si les tests réussissent Le code muté n’a pas été détecté Les tests sont donc insuffisants
  • 25. Loïc Knuchel - @loicknuchel Qu’est-ce qu’un mutant ? def add(item: String): Boolean = { println(s"item add: $item") val exists = items.contains(item) if (items.length < size) { items.append(item) } exists } Code original def add(item: String): Boolean = { () val exists = items.contains(item) if (items.length < size) { items.append(item) } exists } Supprime un appel de fonction def add(item: String): Boolean = { println(s"item add: $item") val exists = items.contains(item) if (true) { items.append(item) } exists } Condition toujours vraie
  • 26. Loïc Knuchel - @loicknuchel Mutations: conditions Modification : < ⇔ <= > ⇔ >= && ⇔ || Constante : true false Inversion : == ⇔ != < ⇔ >= > ⇔ <= cond ⇔ !cond if (items.size() < size) { items.add(item); } if (items.size() <= size) { items.add(item); }
  • 27. Loïc Knuchel - @loicknuchel Mutations: opération mathématique Opérations : x++ ⇔ x-- + ⇔ - * ⇔ / % ⇔ * Opérations binaires : & ⇔ | ^ ⇔ & >> ⇔ << return total - discount; return total + discount;
  • 28. Loïc Knuchel - @loicknuchel Mutations: constantes Change une constante : true ⇔ false 0 ⇔ 1 x ⇔ x + 1 x ⇔ null Remplace une variable par une constante : x ⇔ true / false x ⇔ 0 / 1 / 2 return exists; if(exists == null) throw new RuntimeException(); else return null;
  • 29. Loïc Knuchel - @loicknuchel Mutations: supprimer une fonction println(s"item add: $item")
  • 30. Loïc Knuchel - @loicknuchel Mutations
  • 31. Loïc Knuchel - @loicknuchel En pratique ● mutants uniquement pour le code couvert par les tests ● lance uniquement les tests qui couvrent le code muté ● fonctionne en mode itératif ● à mettre en priorité pour le code critique ● activer que les mutations intéressantes Brute force
  • 32. Loïc Knuchel - @loicknuchel Exemple /** * Take a list of item prices and calculate the bill : * - if total is higher than 50, apply 10% overall discount * - if more than 5 items, apply 100% discount on cheapest one * - if many discount apply, use the higher one */ public static Double getPrice(List<Double> prices) { Double total = sum(prices); Double discount = 0.0; if (total >= 50) { discount = total * 0.1; } if (prices.size() >= 5) { Double minPrice = min(prices); if (minPrice > discount) { discount = minPrice; } } return total - discount; }
  • 33. Loïc Knuchel - @loicknuchel Test 1 @Test public void getPrice_should_be_normal_price_with_few_and_cheap_items() { assertEquals(24, Demo.getPrice(Arrays.asList(4, 7, 1, 12), 0.001); }
  • 34. Loïc Knuchel - @loicknuchel Test 1
  • 35. Loïc Knuchel - @loicknuchel Test 1 + 2 @Test public void getPrice_should_be_get_10pc_discound_on_expensive_items() { assertEquals(54, Demo.getPrice(Arrays.asList(10, 20, 30)), 0.001); }
  • 36. Loïc Knuchel - @loicknuchel Test 1 + 2
  • 37. Loïc Knuchel - @loicknuchel Test 1 + 2 + 3 @Test public void getPrice_should_be_get_one_free_item_when_buy_many() { assertEquals(22, Demo.getPrice(Arrays.asList(3, 5, 2, 8, 1, 4)), 0.001); }
  • 38. Loïc Knuchel - @loicknuchel Test 1 + 2 + 3
  • 39. Loïc Knuchel - @loicknuchel Test 1 + 2 + 3 + 4 @Test public void getPrice_should_should_test_boundary_conditions() { // 50 total value boundary assertEquals(45, Demo.getPrice(Arrays.asList(5, 10, 15, 20)), 0.001); // 5 item boundary assertEquals(43, Demo.getPrice(Arrays.asList(7, 8, 15, 10, 10)), 0.001); }
  • 40. Loïc Knuchel - @loicknuchel Test 1 + 2 + 3 + 4
  • 41. Loïc Knuchel - @loicknuchel Code source https://github.com/loicknuchel/mutation-testing-sample Java / Scala / JavaScript / PR acceptées ;)
  • 42. Loïc Knuchel - @loicknuchel Conclusion Impossible à contourner Long à exécuter Couplage code ⇔ tests Impossible à tuer Tester ses tests Meilleure couverture de code ! Facile à mettre en place
  • 43. Loïc Knuchel - @loicknuchel Questions ? Slides: http://bit.ly/ rivieradev-2018-mutation-testing

Editor's Notes

  1. Bonjour à tous, Bienvenu à mon talk sur le mutation testing.
  2. Je me présente, Loïc Knuchel, je suis développeur Scala chez Criteo, j’organise les HumanTalks et j’essaie de faire du bon code… Je m’intéresse notamment à tous ces sujets, et maintenant aussi au mutation testing
  3. En tant que développeurs, on essaie tous de faire du bon code Mais on a pas forcément tous la même définition du “bon code” A minima on peut probablement s’entendre sur le fait que le code doit : avoir un minimum de bugs rester lisible pour les autres développeurs ne pas demander des efforts disproportionnés pour être modifié
  4. Et bien sûr, pour le premier point, on va écrire des tests
  5. Plein de tests Des tests unitaires qui vont vérifier que chaque morceau de code fait bien ce qu’on attend de lui Des tests d’intégration qui vont s’assurer que les composants n’aient pas d’incompatibilités Des tests de bout en bout pour vérifier que l’application est capable d’exécuter les actions voulues par l’utilisateur Parfois des tests de charge pour prévenir les indisponibilités liées au nombre de requêtes Voire même des chaos monkey tests pour être certain que même en cas de problème, on puisse conserver un certain service
  6. Et tout ça dans un seul but: avoir une application qui fonctionne au maximum comme attendu Mais comment savoir si nos tests garantissent vraiment ça ?
  7. On va devoir tester nos tests => testception
  8. Solution 1: le feeling On connaît bien notre application On a écrit plein de tests On a peu de problèmes en prod Bref, on se dit que ça ne doit pas être mal Et si on est sérieux avec ça, c’est déjà un très bon point
  9. Solution 2: la couverture de code Qui connait ? Ici on lance nos tests et on regarde quels sont les lignes qui ont été exécutées.
  10. ça donne une première idée de la qualité de nos tests clairement, avec une couverture de code faible, on comprends vite que les parties non couvertes sont à risque car pas du tout exécutées lors des tests mais la réciproque n’est pas vraie, une bonne couverture de code ne garantit absolument pas des bon tests.
  11. Lorsque le code est exécuté, il n’est pas forcément vérifié => assert manquant ou assert que sur une partie des résultats ou assert non pertinent c’est pourquoi quand on écrit un test, on doit toujours le faire échouer avant de le faire réussir, mais ça, c’est possible uniquement lorsqu’on le crée, après impossible de s’en assurer on peut aussi avoir un effet difficilement testable voire invisible du point de vue des tests => ex: logger dans ce cas il est exécuté du coup il compte dans la couverture de code, mais pas vérifié
  12. Lorsque le code est exécuté, il n’est pas forcément vérifié => assert manquant ou assert que sur une partie des résultats ou assert non pertinent c’est pourquoi quand on écrit un test, on doit toujours le faire échouer avant de le faire réussir, mais ça, c’est possible uniquement lorsqu’on le crée, après impossible de s’en assurer on peut aussi avoir un effet difficilement testable voire invisible du point de vue des tests => ex: logger dans ce cas il est exécuté du coup il compte dans la couverture de code, mais pas vérifié
  13. Lorsque le code est exécuté, il n’est pas forcément vérifié => assert manquant ou assert que sur une partie des résultats ou assert non pertinent c’est pourquoi quand on écrit un test, on doit toujours le faire échouer avant de le faire réussir, mais ça, c’est possible uniquement lorsqu’on le crée, après impossible de s’en assurer on peut aussi avoir un effet difficilement testable voire invisible du point de vue des tests => ex: logger dans ce cas il est exécuté du coup il compte dans la couverture de code, mais pas vérifié On peut aussi oublier de tester une valeur particulière importante => condition aux limites
  14. Comme toute métrique, elle peut être détournée => introspection pour tout exécuter en un test
  15. et enfin, toutes les lignes de code ne se valent pas, certaines sont beaucoup plus importantes que d’autres et on veut s’assurer que les parties importantes sont très bien testées la couverture de code donne principalement un chiffre global pas forcément pertinent La couverture de code, c’est bien mais loin d’être suffisant.
  16. Heureusement, aujourd’hui je vous présente la solution ultime !!! Ou presque… Enfin, une meilleure solution que les précédentes en tout cas ;) Le mutation testing ! Contrairement à ce que son nom pourrait faire penser, c’est pas une nouvelle méthode de test mais une méthode pour évaluer la qualité des tests, un peu comme la couverture de code D’ailleurs, comme la couverture de code, c’est une technique non-intrusive pour le code de l’application Il suffit simplement de configurer un outil, qui peut être totalement extérieur au code ! Le mutation testing peut être utilisé dans n’importe quel langage mais chaque langage a son outil spécifique.
  17. Par exemple en Java il y a PIT Et pour l’utiliser il suffit de l’ajouter au build et de le lancer C’est aussi simple que ça ! (bien sûr il y a pas mal d’options si on souhaite mais la première intégration est triviale)
  18. En scala il y a scalamu et de la même manière, il suffit de l’ajouter comme plugin et de le lancer
  19. Et enfin, en JavaScript on a stryker
  20. Mais on a toujours pas parlé de ce que fait le mutation testing…
  21. Le principe est très simple Le framework de mutation testing va créer des mutants et vérifier s’ils sont détectés pour les tests
  22. bien sûr, tout ça est assez coûteux en terme de performances… Il est important que les tests s’exécutent rapidement et n’aient pas une portée trop large Et bien sûr il y a quelques optimisations possibles pour améliorer ça