Mutasjonstesting med PITest

1. Oversikt

Programvaretesting refererer til teknikkene som brukes til å vurdere funksjonaliteten til et program. I denne artikkelen skal vi diskutere noen av beregningene som brukes i programvaretestingsindustrien, for eksempel kodedekning og mutasjonstesting, med spesiell interesse for hvordan du utfører en mutasjonstest ved hjelp av PITest bibliotek.

For enkelhets skyld skal vi basere denne demonstrasjonen på en grunnleggende palindromfunksjon - Merk at et palindrom er en streng som leser det samme bakover og fremover.

2. Maven-avhengigheter

Som du kan se i Maven-avhengighetskonfigurasjonen, bruker vi JUnit til å kjøre testene våre og PITEST bibliotek å introdusere mutanter i koden vår - ikke bekymre deg, vi vil se om et sekund hva en mutant er. Du kan alltid slå opp den siste avhengighetsversjonen mot Maven Central Repository ved å følge denne lenken.

 org.pitest pitest-parent 1.1.10 pom 

For å ha PITest-biblioteket i gang, må vi også inkludere ynkeligste-maven plugin i vår pom.xml konfigurasjonsfil:

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

3. Prosjektoppsett

Nå som vi har konfigurert våre Maven-avhengigheter, la oss ta en titt på denne selvforklarende palindromfunksjonen:

public boolean isPalindrome (String inputString) {if (inputString.length () == 0) {return true; } annet {char firstChar = inputString.charAt (0); char lastChar = inputString.charAt (inputString.length () - 1); Streng midt = inputString.substring (1, inputString.length () - 1); retur (firstChar == lastChar) && isPalindrome (mid); }} 

Alt vi trenger nå er en enkel JUnit-test for å sikre at implementeringen vår fungerer på ønsket måte:

@Test offentlig ugyldig nårPalindrom_thenAccept () {Palindrome palindromeTester = new Palindrome (); assertTrue (palindromeTester.isPalindrome ("noon")); } 

Så langt er det bra, vi er klare til å kjøre testsaken vår vellykket som en JUnit-test.

Deretter, i denne artikkelen, skal vi fokusere på kode og mutasjonsdekning ved hjelp av PITest-biblioteket.

4. Kodedekning

Kodedekning har blitt brukt mye i programvareindustrien for å måle hvilken prosent av utførelsesveier har blitt utøvd under automatiserte tester.

Vi kan måle effektiv kodedekning basert på kjøringsveier ved hjelp av verktøy som Eklemma tilgjengelig på Eclipse IDE.

Etter å ha løpt TestPalindrome med kodedekning kan vi enkelt oppnå 100% dekningsresultat - Merk det erPalindrome er rekursivt, så det er ganske åpenbart at tom inngangslengdekontroll vil bli dekket uansett.

Dessverre kan beregninger for kodedekning noen ganger være ganske ineffektiv, fordi en 100% kode dekkingspoeng bare betyr at alle linjene ble utøvd minst en gang, men det sier ingenting om tester nøyaktighet eller fullstendig bruk av tilfeller, og det er derfor mutasjonstesting faktisk betyr noe.

5. Mutasjonsdekning

Mutasjonstesting er en testteknikk som brukes til forbedre tilstrekkelig av tester og identifisere feil i kode. Tanken er å endre produksjonskoden dynamisk og få testene til å mislykkes.

Gode ​​tester skal mislykkes

Hver endring i koden kalles a mutant, og det resulterer i en endret versjon av programmet, kalt a mutasjon.

Vi sier at mutasjonen er det drept hvis det kan føre til svikt i testene. Vi sier også at mutasjonen overlevde hvis mutanten ikke kunne påvirke oppførselen til testene.

La oss nå kjøre testen med Maven, med målalternativet satt til: org.pitest: pitest-maven: mutationCoverage.

Vi kan sjekke rapportene i HTML-format i mål / pit-test / ÅÅÅÅMMDDHHMI katalog:

  • 100% linjedekning: 7/7
  • 63% mutasjonsdekning: 5/8

Det er klart at testen vår feier over alle utførelsesbanene, og dermed er linjedekningen 100%. På den annen side introduserte PITest-biblioteket 8 mutanter, 5 av dem ble drept - forårsaket en fiasko - men 3 overlevde.

Vi kan sjekke com.baeldung.testing.mutation / Palindrome.java.html rapport for mer informasjon om mutanter opprettet:



Dette er mutatorer som er aktive som standard når du kjører en mutasjonsdekningstest:

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

For mer informasjon om PITest-mutatorer, kan du sjekke tjenestemannen dokumentasjonsside lenke.

Vår mutasjonsdekkingspoeng gjenspeiler mangel på prøvesaker, da vi ikke kan sørge for at palindromfunksjonen vår avviser ikke-palindromiske og nesten palindromiske strenginnganger.

6. Forbedre mutasjonspoengene

Nå som vi vet hva en mutasjon er, må vi forbedre mutasjonspoengene våre med drepe de overlevende mutantene.

La oss ta den første mutasjonen - negert betinget - på linje 6 som et eksempel. Mutanten overlevde fordi selv om vi endrer kodebiten:

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

Til:

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

Testen vil bestå, og det er derfor mutasjonen overlevde. Ideen er å implementere en ny test som vil mislykkes, i tilfelle mutanten blir introdusert. Det samme kan gjøres for de gjenværende mutantene.

@Test offentlig ugyldig nårNotPalindrom_thanReject () {Palindrome palindromeTester = new Palindrome (); assertFalse (palindromeTester.isPalindrome ("boks")); } @Test offentlig ugyldig nårNærPalindrom_thanReject () {Palindrome palindromeTester = new Palindrome (); assertFalse (palindromeTester.isPalindrome ("neon")); }

Nå kan vi kjøre testene våre ved hjelp av plugin for mutasjonsdekning, for å være sikker på at alle mutasjonene ble drept, som vi kan se i PITest-rapporten generert i målkatalogen.

  • 100% linjedekning: 7/7
  • 100% mutasjonsdekning: 8/8

7. PITest Tests Configuration

Mutasjonstesting kan være ressurskrevende noen ganger, så vi må sette riktig konfigurasjon på plass for å forbedre testens effektivitet. Vi kan benytte oss av targetClasses for å definere listen over klasser som skal muteres. Mutasjonstesting kan ikke brukes på alle klasser i et virkelig verdensprosjekt, da det vil være tidkrevende og ressurskritisk.

Det er også viktig å definere mutatorene du planlegger å bruke under mutasjonstesting, for å minimere beregningsressursene som trengs for å utføre testene:

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

Videre tilbyr PITest-biblioteket en rekke alternativer tilgjengelig for tilpasse teststrategiene dine, kan du spesifisere maksimalt antall mutanter introdusert av klasse ved hjelp av maxMutationsPerClass alternativ for eksempel. Mer informasjon om PITest-alternativene i den offisielle Maven hurtigstartguide.

8. Konklusjon

Merk at kodedekning fortsatt er en viktig beregning, men noen ganger er det ikke tilstrekkelig til å garantere en godt testet kode. Så i denne artikkelen har vi gått gjennom mutasjonstesting som en mer sofistikert måte å sikre testkvalitet og godkjenne testtilfeller ved hjelp av PITest bibliotek.

Vi har også sett hvordan vi kan analysere grunnleggende PITest-rapporter mens vi forbedrer mutasjonsdekning.

Selv om mutasjonstesting avdekker mangler i koden, bør den brukes med omhu, fordi den er ekstremt kostbar og tidkrevende prosess.

Du kan sjekke eksemplene som er gitt i denne artikkelen i lenken GitHub-prosjekt.


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