A nostra divisione crea pipeline cumplettamente automatiche per lancià novi versioni di applicazioni in l'ambiente di produzzione. Di sicuru, questu hè bisognu di teste funziunali automatizati. Sottu u cut hè una storia nantu à cumu, cuminciendu cù una prova di filu unicu nantu à una macchina lucale, avemu ghjuntu à u puntu di l'autotest multi-threaded in esecuzione in Selenoid in a pipeline di custruzzione cù un rapportu Allure nantu à e pagine di GitLab è, eventualmente, uttene un strumentu d'automatizazione cool. chì e persone futuri ponu aduprà squadre.
Induve avemu principiatu ?
Per implementà l'autotests è integrà in u pipeline, avemu bisognu di un quadru d'automatizazione chì puderia esse cambiatu in modu flessibile per adattà à i nostri bisogni. Ideale, vulia ottene un standard unicu per u mutore di l'autotest, adattatu per incrustà l'autotest in u pipeline. Per l'implementazione avemu sceltu e seguenti tecnulugia:
- Java,
- Maven,
- seleniu,
- Cucumber + JUNIT 4,
- Allure,
- GitLab.
Perchè stu set particulare? Java hè una di e lingue più populari per i testi automatizati, è tutti i membri di a squadra a parlanu. U seleniu hè a suluzione ovvia. Cucumber, tra l'altri cose, duverebbe aumentà a fiducia in i risultati di e teste automatizate da parte di i dipartimenti implicati in testi manuali.
Testi unicu filatu
Per ùn reinventà a rota, avemu pigliatu sviluppi da diversi repositori in GitHub cum'è a basa per u quadru è l'adattamu per noi. Avemu creatu un repository per a biblioteca principale cù u core di u quadru di l'autotest è un repository cù un esempiu Gold di implementazione di autotest in u nostru core. Ogni squadra hà avutu à piglià l'imaghjini d'oru è sviluppà testi in questu, adattendu à u so prughjettu. L'avemu implementatu à u bancu GitLab-CI, nantu à quale avemu cunfiguratu:
- corse ogni ghjornu di tutti l'autotest scritti per ogni prughjettu;
- lancia in u pipeline di custruzzione.
À u principiu, ci sò stati pochi testi, è sò stati realizati in un flussu. L'esecuzione di un filu unicu nantu à u Windows runner GitLab ci hè stata abbastanza bè: i testi anu caricatu u bancu di prova assai ligeramente è ùn anu utilizatu quasi nisuna risorsa.
À u tempu, u nùmeru di l'autotests hè diventatu più è più numarosi, è avemu pensatu à eseguisce in parallelu, quandu una corsa sana cuminciò à piglià circa trè ore. Altri prublemi apparsu ancu:
- ùn pudemu micca verificà chì i testi eranu stabili;
- e teste chì sò state eseguite parechje volte in una fila nantu à a macchina lucale qualchì volta si scontranu in CI.
Esempiu di stallà autotests:
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.20</version>
<configuration>
<skipTests>${skipTests}</skipTests>
<testFailureIgnore>false</testFailureIgnore>
<argLine>
-javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar"
-Dcucumber.options="--tags ${TAGS} --plugin io.qameta.allure.cucumber2jvm.AllureCucumber2Jvm --plugin pretty"
</argLine>
</configuration>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectj.version}</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>io.qameta.allure</groupId>
<artifactId>allure-maven</artifactId>
<version>2.9</version>
</plugin>
</plugins>
Esempiu di rapportu Allure
Carica di runner durante e teste (8 core, 8 GB RAM, 1 thread)
Pro di i testi unicu filatu:
- faciule d'installà è curriri;
- i lanci in CI sò praticamenti micca diffirenti da i lanciamenti lucali;
- e teste ùn anu micca affettu l'altri;
- requisiti minimi per e risorse di i corridori.
I svantaghji di e teste à filu unicu:
- piglià assai tempu per compie;
- longa stabilizazione di e teste;
- usu inefficace di risorse di corridore, usu estremamente bassu.
Testi nantu à fork JVM
Siccomu ùn avemu micca cura di u codice thread-safe quandu implementava u quadru di basa, u modu più ovvi di eseguisce in parallelu era
U servitore Selenoid hè stata lanciata nantu à una macchina cù core 32 è 24 GB di RAM. U limitu hè statu stabilitu à 48 navigatori - 1,5 fili per core è circa 400 MB di RAM. In u risultatu, u tempu di prova hè stata ridutta da trè ore à 40 minuti. L'accelerazione di e corse hà aiutatu à risolve u prublema di stabilizazione: avà pudemu eseguisce rapidamente novi autotests 20-30 volte finu à chì eramu sicuri ch'elli correvanu in modu affidabile.
U primu svantaghju di a suluzione hè stata l'alta utilizazione di e risorse di u corridore cù un picculu numeru di filamenti paralleli: nantu à 4 core è 8 GB di RAM, i testi currenu stabile in micca più di fili 6. U sicondu svantaghju: u plugin genera classi di runner per ogni scenariu, ùn importa quanti di elli sò lanciati.
Impurtante! Ùn passa micca una variabile cù tags à argLine, per esempiu, cusì:
<argLine>-Dcucumber.options="--tags ${TAGS} --plugin io.qameta.allure.cucumber2jvm.AllureCucumber2Jvm --plugin pretty"</argLine>
…
Mvn –DTAGS="@smoke"
Se passate l'etichetta in questu modu, u plugin generà corridori per tutti i testi, vale à dì, pruvarà à eseguisce tutte e teste, saltendu immediatamente dopu à u lanciu è creendu assai forche JVM.
Hè currettu per scaccià una variabile cù un tag in Corsica tags in i paràmetri di u plugin, vede l'esempiu sottu. Altri metudi chì avemu pruvatu anu prublemi per cunnette u plugin Allure.
Esempiu di tempu di esecuzione per 6 teste brevi cù paràmetri sbagliati:
[INFO] Total time: 03:17 min
Esempiu di u tempu di esecuzione di a prova si trasferisce direttamente u tag à mvn... –Dcucumber.opzioni:
[INFO] Total time: 44.467 s
Esempiu di stallà autotests:
<profiles>
<profile>
<id>parallel</id>
<build>
<plugins>
<plugin>
<groupId>com.github.temyers</groupId>
<artifactId>cucumber-jvm-parallel-plugin</artifactId>
<version>5.0.0</version>
<executions>
<execution>
<id>generateRunners</id>
<phase>generate-test-sources</phase>
<goals>
<goal>generateRunners</goal>
</goals>
<configuration>
<tags>
<tag>${TAGS}</tag>
</tags>
<glue>
<package>stepdefs</package>
</glue>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.21.0</version>
<configuration>
<forkCount>12</forkCount>
<reuseForks>false</reuseForks>
<includes>**/*IT.class</includes>
<testFailureIgnore>false</testFailureIgnore>
<!--suppress UnresolvedMavenProperty -->
<argLine>
-javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar" -Dcucumber.options="--plugin io.qameta.allure.cucumber2jvm.AllureCucumber2Jvm TagPFAllureReporter --plugin pretty"
</argLine>
</configuration>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectj.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</profile>
Esempiu di un rapportu Allure (a prova più instabile, 4 ripetizioni)
Carica di runner durante i testi (8 core, 8 GB di RAM, 12 thread)
Pros:
- installazione faciule - basta à aghjunghje un plugin;
- a capacità di realizà simultaneamente un gran numaru di teste;
- accelerazione di stabilizazione di prova grazia à u passu 1.
Cons:
- Multiple OS / cuntenituri necessarii;
- altu cunsumu di risorse per ogni forchetta;
- U plugin hè obsoleto è ùn hè più supportatu.
Cumu superà a inestabilità
I banchi di prova ùn sò micca ideali, cum'è l'autotesti stessi. Ùn hè micca surprisante chì avemu una quantità di teste flacky. Venutu in salvezza
Esempiu di stallà autotests:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.21.0</version>
<configuration>
….
<rerunFailingTestsCount>2</rerunFailingTestsCount>
….
</configuration>
</plugin>
O à l'iniziu: mvn... -Dsurefire.rerunFailingTestsCount=2...
Comu opzione, stabilisce l'opzioni Maven per u script PowerShell (PS1):
Set-Item Env:MAVEN_OPTS "-Dfile.encoding=UTF-8 -Dsurefire.rerunFailingTestsCount=2"
Pros:
- ùn ci hè bisognu di perde u tempu per analizà una prova inestabile quandu si crash;
- I prublemi di stabilità di u bancu di teste ponu esse mitigati.
Cons:
- i difetti flottanti ponu esse mancati;
- u tempu di corsa aumenta.
Testi paralleli cù a biblioteca Cucumber 4
U numeru di testi cresce ogni ghjornu. Avemu pensatu di novu à accelerà e corse. Inoltre, aghju vulsutu integrà quant'è più teste pussibule in u pipeline di assemblea di l'applicazione. U fattore criticu era chì a generazione di corridori pigliò troppu longu quandu correva in parallelu cù u plugin Maven.
À quellu tempu, Cucumber 4 era digià statu liberatu, cusì avemu decisu di riscrive u kernel per questa versione. In e note di liberazione ci hè statu prumessu di lanciamentu parallelu à u livellu di filu. In teoria, deve esse:
- accelerà significativamente a corsa di l'autotest aumentendu u numeru di fili;
- eliminà a perdita di tempu nantu à a generazione di corridori per ogni autotest.
L'ottimisazione di u quadru per l'autotest multi-threaded ùn hè micca cusì difficiule. Cucumber 4 esegue ogni prova individuale nantu à un filu dedicatu da u principiu à a fine, cusì alcune cose statiche cumuni sò stati cunvertiti solu in variabili ThreadLocal.
A cosa principalu quandu si cunvertisce cù l'arnesi di refactoring Idea hè di verificà i posti induve a variàbile hè stata paragunata (per esempiu, cuntrollà per null). Inoltre, avete bisognu di aghjunghje u plugin Allure à l'annotazione di classi Junit Runner.
Esempiu di stallà autotests:
<profile>
<id>parallel</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M3</version>
<configuration>
<useFile>false</useFile>
<testFailureIgnore>false</testFailureIgnore>
<parallel>methods</parallel>
<threadCount>6</threadCount>
<perCoreThreadCount>true</perCoreThreadCount>
<argLine>
-javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar"
</argLine>
</configuration>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectj.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</profile>
Esempiu di un rapportu Allure (a prova più instabile, 5 ripetizioni)
Carica di runner durante i testi (8 core, 8 GB di RAM, 24 thread)
Pros:
- bassu cunsumu di risorse;
- supportu nativu da Cucumber - ùn hè micca necessariu strumenti supplementari;
- a capacità di eseguisce più di 6 fili per core di processore.
Cons:
- avete bisognu di assicurà chì u codice sustene l'esekzione multi-threaded;
- a soglia di entrata aumenta.
Allure rapporti nantu à e pagine di GitLab
Dopu avè introduttu l'esecuzione multi-threaded, avemu cuminciatu à passà assai più tempu per analizà i rapporti. À quellu tempu, avemu avutu a carica ogni rapportu cum'è un artefattu à GitLab, dopu scaricallu è unpack lu. Ùn hè micca assai còmuda è dura assai tempu. È s'ellu qualcunu vole vede u rapportu per ellu stessu, allora avarà bisognu di fà e stesse operazioni. Vulemu riceve feedback più veloce, è avemu trovu una suluzione - pagine GitLab. Questa hè una funzione integrata chì hè dispunibule fora di a scatula in tutte e versioni recenti di GitLab. Permette di implementà siti statici in u vostru servitore è accede à elli via un ligame direttu.
Tutte e screenshots di i rapporti Allure sò stati pigliati nantu à e pagine di GitLab. Script per implementà u rapportu à e pagine GitLab - in Windows PowerShell (prima di questu avete bisognu di eseguisce autotests):
New-Item -ItemType directory -Path $testresulthistory | Out-Null
try {Invoke-WebRequest -Uri $hst -OutFile $outputhst}
Catch{echo "fail copy history"}
try {Invoke-WebRequest -Uri $hsttrend -OutFile $outputhsttrnd}
Catch{echo "fail copy history trend"}
mvn allure:report
#mvn assembly:single -PzipAllureReport
xcopy $buildlocationtargetsiteallure-maven-plugin* $buildlocationpublic /s /i /Y
Chì ghjè a linea di fondu
Allora, s'è vo pensate s'ellu avete bisognu di u codice Thread safe in u framework Cucumber autotest, avà a risposta hè ovvia - cù Cucumber 4 hè faciule da implementà, cusì aumentendu significativamente u numeru di fili lanciati simultaneamente. Cù stu metudu di eseguisce e teste, a quistione diventa avà nantu à u rendiment di a macchina cù Selenoid è u bancu di prova.
A pratica hà dimustratu chì eseguisce autotests nantu à i fili permette di riduce u cunsumu di risorse à u minimu cù u megliu rendimentu. Comu pò esse vistu da i grafici, i fili di duppiu ùn portanu micca à una accelerazione simili in i testi di rendiment. Tuttavia, avemu pussutu aghjunghje più di 2 teste automatizati à a custruzione di l'applicazione, chì ancu cù 200 reruns run in circa 5 minuti. Questu permette di riceve un feedback rapidu da elli, è, se ne necessariu, fate cambiamenti è ripetite a prucedura di novu.
Source: www.habr.com