Kjører JUnit-tester parallelt med Maven

1. Introduksjon

Selv om det er bra å utføre serier det meste av tiden, kan det være lurt å parallellisere dem for å øke hastigheten.

I denne opplæringen vil vi dekke hvordan du kan parallellisere tester med JUnit og Mavens Surefire Plugin. Først kjører vi alle testene i en enkelt JVM-prosess, og deretter prøver vi det med et multimodulprosjekt.

2. Maven-avhengigheter

La oss begynne med å importere de nødvendige avhengighetene. Vi må bruke JUnit 4.7 eller senere sammen med Surefire 2.16 eller nyere:

 junit junit 4.12 test 
 org.apache.maven.plugins maven-surefire-plugin 2.22.0 

I et nøtteskall gir Surefire to måter å utføre tester parallelt på:

  • Multitrading i en enkelt JVM-prosess
  • Forking av flere JVM-prosesser

3. Kjører parallelle tester

For å kjøre en test parallelt, bør vi bruke en testløper som strekker seg org.junit.runners.ParentRunner.

Imidlertid fungerer til og med tester som ikke erklærer eksplisitt testløper, da standardløper utvider denne klassen.

Deretter, for å demonstrere parallell testutførelse, bruker vi en testpakke med to testklasser som hver har noen få metoder. Faktisk vil enhver standardimplementering av en JUnit-testpakke gjøre det.

3.1. Ved hjelp av parallellparameter

La oss først aktivere parallell oppførsel i Surefire ved hjelp av parallell parameter. Den angir nivået på granularitet som vi vil bruke parallellisme.

De mulige verdiene er:

  • metoder - kjører testmetoder i separate tråder
  • klasser - kjører testklasser i separate tråder
  • classesAndMethods - kjører klasser og metoder i separate tråder
  • suiter - kjører suiter parallelt
  • suitesAndClasses - kjører suiter og klasser i separate tråder
  • suitesAndMethods - lager separate tråder for klasser og metoder
  • alle - kjører suiter, klasser samt metoder i separate tråder

I vårt eksempel bruker vi alle:

 alle 

For det andre, la oss definere det totale antallet tråder vi vil at Surefire skal lage. Vi kan gjøre det på to måter:

Ved hjelp av threadCount som definerer maksimalt antall tråder Surefire vil opprette:

10

Eller bruke useUnlimitedThreads parameter der en tråd opprettes per CPU-kjerne:

ekte

Som standard, threadCount er per CPU-kjerne. Vi kan bruke parameteren perCoreThreadCount for å aktivere eller deaktivere denne oppførselen:

ekte

3.2. Bruke begrensninger for trådtelling

La oss si at vi vil definere antall tråder som skal opprettes på metode-, klasse- og suite-nivå. Vi kan gjøre dette med threadCountMethods, threadCountClasses og threadCountSuites parametere.

La oss kombinere disse parametrene med threadCount fra forrige konfigurasjon:

2 2 6

Siden vi brukte alle i parallell, Vi har definert trådtellingen for metoder, suiter og klasser. Det er imidlertid ikke obligatorisk å definere bladparameteren. Surefire trekker ut antall tråder som skal brukes i tilfelle bladparametere utelates.

For eksempel hvis threadCountMethods er utelatt, så trenger vi bare å sørge for threadCount >threadCountClasses + threadCountSuites.

Noen ganger kan det være lurt å begrense antall tråder som er opprettet for klasser eller suiter eller metoder, selv når vi bruker et ubegrenset antall tråder.

Vi kan også bruke trådtellingbegrensninger i slike tilfeller:

sant 2

3.3. Stille inn tidsavbrudd

Noen ganger kan det hende vi må sørge for at testutførelsen er tidsbegrenset.

For å gjøre det kan vi bruke parallelTestTimeoutForcedInSeconds parameter. Dette vil avbryte trådene som for øyeblikket kjører, og vil ikke utføre noen av trådene i kø etter at tidsavbruddet har gått:

5

Et annet alternativ er å bruke parallelTestTimeoutInSeconds.

I dette tilfellet vil bare trådene i kø stoppes fra å kjøres:

3.5

Likevel, med begge alternativene, vil testene ende med en feilmelding når tidsavbruddet har gått.

3.4. Advarsler

Surefire kaller statiske metoder merket med @Parametere, @BeforeClass, og @Etter timen i overordnet tråd. Sørg derfor for å sjekke for potensielle minneinkonsekvenser eller løpsforhold før du kjører tester parallelt.

Også tester som muterer delt tilstand er definitivt ikke gode kandidater for å kjøre parallelt.

4. Test utførelse i multimodul Maven-prosjekter

Til nå har vi fokusert på å kjøre tester parallelt i en Maven-modul.

Men la oss si at vi har flere moduler i et Maven-prosjekt. Siden disse modulene er bygget sekvensielt, blir testene for hver modul også utført sekvensielt.

Vi kan endre denne standardadferden ved å bruke Mavens -T parameter som bygger moduler parallelt. Dette kan gjøres på to måter.

Vi kan enten spesifisere nøyaktig antall tråder som skal brukes når vi bygger prosjektet:

mvn -T 4 surefire: test

Eller bruk den bærbare versjonen og spesifiser antall tråder som skal opprettes per CPU-kjerne:

mvn -T 1C surefire: test

Uansett kan vi øke hastigheten på tester og bygge gjennomføringstider.

5. Forking JVM

Med den parallelle testutførelsen via parallell alternativ, skjer samtidighet i JVM-prosessen ved hjelp av tråder.

Siden tråder deler samme minneplass, kan dette være effektivt når det gjelder minne og hastighet. Vi kan imidlertid støte på uventede løpsforhold eller andre subtile samtidige testfeil. Det viser seg at det å dele det samme minneplassen kan være både en velsignelse og en forbannelse.

For å forhindre trådnivåproblemer gir Surefire en annen parallell testutføringsmodus: forking og samtidig prosessnivå. Ideen om forked prosesser er faktisk ganske enkel. I stedet for å gyte flere tråder og distribuere testmetodene mellom dem, skaper surefire nye prosesser og gjør den samme fordelingen.

Siden det ikke er noe delt minne mellom forskjellige prosesser, vil vi ikke lide av de subtile samtidige feilene. Dette kommer selvfølgelig på bekostning av mer minnebruk og litt mindre hastighet.

Uansett, For å muliggjøre gaffel, må vi bare bruke forkCount eiendom og sett den til en hvilken som helst positiv verdi:

3

Her vil surefire maksimalt skape tre gafler fra JVM og kjøre testene i dem. Standardverdien for forkCount er en, noe som betyr at maven-surefire-plugin oppretter en ny JVM-prosess for å utføre alle tester i en Maven-modul.

De forkCount eiendom støtter den samme syntaksen som -T. Det vil si hvis vi legger til C til verdien, vil den verdien bli multiplisert med antall tilgjengelige CPU-kjerner i systemet vårt. For eksempel:

2.5C

Så i en to-kjernemaskin kan Surefire opprette maksimalt fem gafler for parallell testutførelse.

Som standard, Surefire vil bruke de opprettet gaflene til andre tester. Imidlertid, hvis vi setter gjenbrukForks eiendom til falsk, vil den ødelegge hver gaffel etter å ha kjørt en testklasse.

For å deaktivere gaffelen kan vi også stille inn forkCount til null.

6. Konklusjon

For å oppsummere startet vi med å muliggjøre atferd med flere tråder og definere graden av parallellitet ved hjelp av parallell parameter. Deretter brukte vi begrensninger på antall tråder Surefire burde opprette. Senere setter vi tidsavbruddsparametere for å kontrollere testutføringstidene.

Til slutt så vi på hvordan vi kan redusere utførelsestider og derfor teste utførelsestider i Maven-prosjekter med flere moduler.

Som alltid er koden presentert her tilgjengelig på GitHub.


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