Mutatietesten met PITest

1. Overzicht

Softwaretesting verwijst naar de technieken die worden gebruikt om de functionaliteit van een softwareapplicatie te beoordelen. In dit artikel gaan we enkele van de statistieken bespreken die worden gebruikt in de softwaretestindustrie, zoals code dekking en mutatie testen, met bijzondere belangstelling voor het uitvoeren van een mutatietest met behulp van de PITest-bibliotheek.

Eenvoudigheidshalve gaan we deze demonstratie baseren op een elementaire palindroomfunctie. Merk op dat een palindroom een ​​tekenreeks is die achterwaarts en voorwaarts hetzelfde leest.

2. Maven afhankelijkheden

Zoals u kunt zien in de configuratie van Maven-afhankelijkheden, zullen we JUnit gebruiken om onze tests uit te voeren en het PITest bibliotheek om te introduceren mutanten in onze code - maak je geen zorgen, we zullen zo zien wat een mutant is. U kunt altijd de laatste afhankelijkheidsversie opzoeken in de centrale opslagplaats van maven door deze link te volgen.

 org.pitest pitest-parent 1.1.10 pom 

Om de PITest-bibliotheek actief te hebben, moeten we ook het pitest-maven plug-in in onze pom.xml configuratiebestand:

 org.pitest pitest-maven 1.1.10 com.baeldung.testing.mutation. * com.baeldung.mutation.test. * 

3. Projectconfiguratie

Nu we onze Maven-afhankelijkheden hebben geconfigureerd, laten we eens kijken naar deze voor zichzelf sprekende palindroomfunctie:

openbare boolean isPalindrome (String inputString) {if (inputString.length () == 0) {return true; } anders {char firstChar = inputString.charAt (0); char lastChar = inputString.charAt (inputString.length () - 1); String mid = inputString.substring (1, inputString.length () - 1); return (firstChar == lastChar) && isPalindrome (mid); }} 

Het enige dat we nu nodig hebben, is een eenvoudige JUnit-test om ervoor te zorgen dat onze implementatie op de gewenste manier werkt:

@Test openbare leegte whenPalindrom_thenAccept () {Palindrome palindromeTester = nieuwe Palindrome (); assertTrue (palindromeTester.isPalindrome ("middag")); } 

Tot zover goed, we zijn klaar om onze testcase met succes uit te voeren als een JUnit-test.

Vervolgens gaan we ons in dit artikel concentreren op code en mutatiedekking met behulp van de PITest-bibliotheek.

4. Codedekking

Codedekking is op grote schaal gebruikt in de software-industrie om te meten welk percentage van de uitvoeringspaden is uitgeoefend tijdens geautomatiseerde tests.

We kunnen de effectieve codedekking meten op basis van uitvoeringspaden met behulp van tools zoals Eclemma beschikbaar op Eclipse IDE.

Na het rennen TestPalindroom met codedekking kunnen we gemakkelijk een dekkingsscore van 100% behalen - Merk op dat isPalindroom is recursief, dus het is vrij duidelijk dat de controle van de lege invoerlengte hoe dan ook wordt afgedekt.

Helaas kunnen de statistieken voor codedekking soms behoorlijk zijn niet effectief, omdat een score van 100% codedekking alleen betekent dat alle regels minstens één keer zijn uitgeoefend, maar daar staat niets over test nauwkeurigheid of use-cases volledigheid, en dat is waarom mutatietesten er echt toe doen.

5. Mutatiedekking

Mutatietesten is een testtechniek die wordt gebruikt de toereikendheid verbeteren van tests en identificeer defecten in code. Het idee is om de productiecode dynamisch te wijzigen en ervoor te zorgen dat de tests mislukken.

Goede tests zullen mislukken

Elke wijziging in de code wordt een mutant, en het resulteert in een gewijzigde versie van het programma, genaamd een mutatie.

We zeggen dat de mutatie is gedood als het een mislukking in de tests kan veroorzaken. We zeggen ook dat de mutatie overleefde als de mutant het gedrag van de tests niet kon beïnvloeden.

Laten we nu de test uitvoeren met Maven, met de doeloptie ingesteld op: org.pitest: pitest-maven: mutationCoverage.

We kunnen de rapporten in HTML-formaat bekijken in de target / pit-test / YYYYMMDDHHMI directory:

  • 100% lijndekking: 7/7
  • 63% mutatiedekking: 5/8

Het is duidelijk dat onze test alle uitvoeringspaden doorkruist, dus de lijndekkingsscore is 100%. Aan de andere kant introduceerde de PITest-bibliotheek 8 mutanten, 5 van hen werden gedood - veroorzaakte een mislukking - maar 3 overleefden.

We kunnen de com.baeldung.testing.mutation / Palindrome.java.html rapport voor meer details over de aangemaakte mutanten:



Dit zijn de mutators standaard actief bij het uitvoeren van een mutatiedekkingstest:

  • INCREMENTS_MUTATOR
  • VOID_METHOD_CALL_MUTATOR
  • RETURN_VALS_MUTATOR
  • MATH_MUTATOR
  • NEGATE_CONDITIONALS_MUTATOR
  • INVERT_NEGS_MUTATOR
  • CONDITIONALS_BOUNDARY_MUTATOR

Voor meer details over de PITest-mutatoren, kun je de ambtenaar raadplegen documentatiepagina koppeling.

Onze mutatiedekkingsscore weerspiegelt het ontbreken van testgevallen, omdat we er niet zeker van kunnen zijn dat onze palindroomfunctie niet-palindroom en bijna palindroom stringinvoer afwijst.

6. Verbeter de mutatiescore

Nu we weten wat een mutatie is, moeten we onze mutatiescore met verbeteren het doden van de overlevende mutanten.

Laten we de eerste mutatie - voorwaardelijk genegeerd - op regel 6 als voorbeeld nemen. De mutant heeft het overleefd, want zelfs als we het codefragment wijzigen:

if (inputString.length () == 0) {return true; }

Naar:

if (inputString.length ()! = 0) {return true; }

De test zal slagen, en daarom de mutatie heeft het overleefd. Het idee is om dat een nieuwe test uit te voeren zal mislukken als de mutant wordt geïntroduceerd. Hetzelfde kan worden gedaan voor de overige mutanten.

@Test openbare leegte whenNotPalindrom_thanReject () {Palindrome palindromeTester = nieuwe Palindrome (); assertFalse (palindromeTester.isPalindrome ("box")); } @Test openbare leegte whenNearPalindrom_thanReject () {Palindroom palindromeTester = nieuw Palindroom (); assertFalse (palindromeTester.isPalindrome ("neon")); }

Nu kunnen we onze tests uitvoeren met behulp van de plug-in voor mutatiedekking, om ervoor te zorgen dat alle mutaties werden gedood, zoals we kunnen zien in het PITest-rapport dat is gegenereerd in de doelmap.

  • 100% lijndekking: 7/7
  • 100% mutatiedekking: 8/8

7. Configuratie van PITest-tests

Mutatietesten kunnen soms veel middelen vergen, dus we moeten de juiste configuratie invoeren om de effectiviteit van de tests te verbeteren. We kunnen gebruik maken van de targetClasses tag, om de lijst met te muteren klassen te definiëren. Mutatietesten kunnen niet op alle klassen in een real-world project worden toegepast, omdat het tijdrovend en onmisbaar zal zijn.

Het is ook belangrijk om de mutatoren te definiëren die u wilt gebruiken tijdens het testen van mutaties, om de computerresources die nodig zijn om de tests uit te voeren te minimaliseren:

  com.baeldung.testing.mutation. * com.baeldung.mutation.test. * CONSTRUCTOR_CALLS VOID_METHOD_CALLS RETURN_VALS NON_VOID_METHOD_CALLS 

Bovendien biedt de PITest-bibliotheek een scala aan mogelijkheden voor pas uw teststrategieën aan, kunt u het maximale aantal mutanten dat per klasse wordt geïntroduceerd specificeren met behulp van de maxMutationsPerClass optie bijvoorbeeld. Meer details over PITest-opties in de officiële Snelstartgids voor Maven.

8. Conclusie

Merk op dat codedekking nog steeds een belangrijke statistiek is, maar soms is het niet voldoende om een ​​goed geteste code te garanderen. Dus in dit artikel hebben we er doorheen gelopen mutatie testen als een meer geavanceerde manier om de kwaliteit van tests te waarborgen en testgevallen te onderschrijven, met behulp van de PITest-bibliotheek.

We hebben ook gezien hoe we een basis PITest-rapport kunnen analyseren terwijl we het mutatiedekking score.

Hoewel mutatietesten defecten in de code aan het licht brengen, moet het verstandig worden gebruikt, want het is een extreem kostbaar en tijdrovend proces.

U kunt de voorbeelden in dit artikel bekijken in het gekoppelde GitHub-project.


$config[zx-auto] not found$config[zx-overlay] not found