Implementare, scalare: experiență de utilizare a testelor automate la VTB

Divizia noastră creează conducte complet automate pentru lansarea de noi versiuni de aplicații în mediul de producție. Desigur, acest lucru necesită teste funcționale automate. Mai jos este o poveste despre cum, începând cu testarea cu un singur fir pe o mașină locală, am ajuns la punctul de autotest cu mai multe fire care rulează pe Selenoid în cursul de construire cu un raport Allure pe paginile GitLab și, în cele din urmă, am obținut un instrument de automatizare grozav. că viitorii oameni pot folosi echipe.

Implementare, scalare: experiență de utilizare a testelor automate la VTB

De unde am început?

Pentru a implementa autotestele și pentru a le integra în pipeline, aveam nevoie de un cadru de automatizare care să poată fi modificat în mod flexibil pentru a se potrivi nevoilor noastre. În mod ideal, am vrut să obțin un singur standard pentru motorul de autotestare, adaptat pentru încorporarea autotestelor în conductă. Pentru implementare am ales următoarele tehnologii:

  • java,
  • Maven,
  • Seleniu,
  • Castravete+JUNIT 4,
  • alura,
  • GitLab.

Implementare, scalare: experiență de utilizare a testelor automate la VTB

De ce acest set anume? Java este una dintre cele mai populare limbaje pentru teste automate și toți membrii echipei îl vorbesc. Seleniul este soluția evidentă. Castravetele, printre altele, trebuia să crească încrederea în rezultatele testelor automate din partea departamentelor implicate în testarea manuală.

Teste cu un singur fir

Pentru a nu reinventa roata, am luat dezvoltări din diferite depozite de pe GitHub ca bază pentru cadru și le-am adaptat pentru noi înșine. Am creat un depozit pentru biblioteca principală cu nucleul cadrului de autotest și un depozit cu un exemplu Gold de implementare a autotestelor pe nucleul nostru. Fiecare echipă a trebuit să ia imaginea Gold și să dezvolte teste în ea, adaptând-o la proiectul său. L-am implementat în banca GitLab-CI, pe care am configurat:

  • rulări zilnice ale tuturor autotestelor scrise pentru fiecare proiect;
  • se lansează în curs de construcție.

La început au fost puține teste și au fost efectuate într-un singur flux. Rularea cu un singur thread pe rulerul Windows GitLab ni s-a potrivit destul de bine: testele au încărcat bancul de testare foarte ușor și au folosit aproape deloc resurse.

De-a lungul timpului, numărul de autotestări a devenit din ce în ce mai numeros și ne-am gândit să le rulăm în paralel, când o rulare completă a început să dureze aproximativ trei ore. Au aparut si alte probleme:

  • nu am putut verifica dacă testele au fost stabile;
  • testele care au fost executate de mai multe ori la rând pe mașina locală s-au prăbușit uneori în CI.

Exemplu de configurare a autotestelor:

<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>

 Implementare, scalare: experiență de utilizare a testelor automate la VTB
Exemplu de raport Allure

 Implementare, scalare: experiență de utilizare a testelor automate la VTB
Încărcare runner în timpul testelor (8 nuclee, 8 GB RAM, 1 fir)
 
Avantajele testelor cu un singur fir:

  • ușor de configurat și de rulat;
  • lansările în CI nu sunt practic diferite de lansările locale;
  • testele nu se afectează reciproc;
  • cerințe minime pentru resursele alergătorului.

Dezavantajele testelor cu un singur fir:

  • ia foarte mult timp pentru finalizare;
  • stabilizare îndelungată a testelor;
  • utilizarea ineficientă a resurselor alergătorului, utilizare extrem de scăzută.

Teste pe furcile JVM

Deoarece nu ne-am ocupat de codul thread-safe la implementarea cadrului de bază, cel mai evident mod de a rula în paralel a fost castravete-jvm-paralel-plugin pentru Maven. Pluginul este ușor de configurat, dar pentru o funcționare corectă în paralel, autotestele trebuie să fie rulate în browsere separate. Nu este nimic de făcut, a trebuit să folosesc Selenoid.

Serverul Selenoid a fost lansat pe o mașină cu 32 de nuclee și 24 GB de RAM. Limita a fost stabilită la 48 de browsere - 1,5 fire per nucleu și aproximativ 400 MB de RAM. Ca rezultat, timpul de testare a fost redus de la trei ore la 40 de minute. Accelerarea execuțiilor a ajutat la rezolvarea problemei de stabilizare: acum am putea rula rapid noi autotestări de 20-30 de ori, până când eram siguri că rulează fiabil.
Primul dezavantaj al soluției a fost utilizarea ridicată a resurselor runner cu un număr mic de fire paralele: pe 4 nuclee și 8 GB de RAM, testele au rulat stabil în cel mult 6 fire. Al doilea dezavantaj: pluginul generează clase de alergători pentru fiecare scenariu, indiferent câte dintre ele sunt lansate.

Important! Nu transmiteți o variabilă cu etichete către argLine, de exemplu, astfel:

<argLine>-Dcucumber.options="--tags ${TAGS} --plugin io.qameta.allure.cucumber2jvm.AllureCucumber2Jvm --plugin pretty"</argLine>
…
Mvn –DTAGS="@smoke"

Dacă treceți eticheta în acest fel, pluginul va genera runneri pentru toate testele, adică va încerca să ruleze toate testele, sărind peste ele imediat după lansare și creând multe fork-uri JVM.

Este corect să aruncați o variabilă cu o etichetă în tag-uri în setările pluginului, vezi exemplul de mai jos. Alte metode pe care le-am testat au probleme la conectarea pluginului Allure.

Exemplu de timp de rulare pentru 6 teste scurte cu setări incorecte:

[INFO] Total time: 03:17 min

Exemplu de timp de testare dacă transferați direct eticheta la mvn... –Dcastravete.opţiuni:

[INFO] Total time: 44.467 s

Exemplu de configurare a autotestelor:

<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>

Implementare, scalare: experiență de utilizare a testelor automate la VTB
Exemplu de raport Allure (cel mai instabil test, 4 reluări)

Implementare, scalare: experiență de utilizare a testelor automate la VTBÎncărcare runner în timpul testelor (8 nuclee, 8 GB RAM, 12 fire)
 
Pro-uri:

  • configurare ușoară - trebuie doar să adăugați un plugin;
  • capacitatea de a efectua simultan un număr mare de teste;
  • accelerarea stabilizării testului datorită pasului 1. 

Contra:

  • Sunt necesare mai multe sisteme de operare/containere;
  • consum mare de resurse pentru fiecare furcă;
  • Pluginul este depășit și nu mai este acceptat. 

Cum să depășești instabilitatea 

Bancurile de testare nu sunt ideale, la fel ca autotestele în sine. Nu este surprinzător că avem o serie de teste slăbite. A venit la salvare plugin-ul maven surefire, care acceptă repornirea testelor eșuate. Trebuie să actualizați versiunea pluginului la cel puțin 2.21 și să scrieți o linie cu numărul de reporniri în fișierul pom sau să o transmiteți ca argument lui Maven.

Exemplu de configurare a autotestelor:

   	
<plugin>
        	
<groupId>org.apache.maven.plugins</groupId>
  	
      <artifactId>maven-surefire-plugin</artifactId>
        	
<version>2.21.0</version>
        	
<configuration>
           	
….
            	
<rerunFailingTestsCount>2</rerunFailingTestsCount>
            	
….
            	
</configuration>
</plugin>

Sau la pornire: mvn … -Dsurefire.rerunFailingTestsCount=2 …
Ca opțiune, setați opțiunile Maven pentru scriptul PowerShell (PS1):

  
Set-Item Env:MAVEN_OPTS "-Dfile.encoding=UTF-8 -Dsurefire.rerunFailingTestsCount=2"

Pro-uri:

  • nu este nevoie să pierdeți timpul analizând un test instabil atunci când acesta se blochează;
  • Problemele de stabilitate a bancului de testare pot fi atenuate.

Contra:

  • defectele plutitoare pot fi omise;
  • timpul de rulare crește.

Teste paralele cu biblioteca Castravete 4

Numărul de teste a crescut în fiecare zi. Ne-am gândit din nou să grăbim alergările. În plus, am vrut să integrez cât mai multe teste posibil în conducta de asamblare a aplicației. Factorul critic a fost că generarea de alergători a durat prea mult atunci când rulau în paralel folosind pluginul Maven.

La acel moment, Cucumber 4 fusese deja lansat, așa că am decis să rescriem nucleul pentru această versiune. În notele de lansare ni s-a promis lansarea paralelă la nivel de fir. Teoretic, acesta ar fi trebuit să fie:

  • accelerează semnificativ rularea autotestelor prin creșterea numărului de fire;
  • eliminați pierderea de timp la generarea de alergători pentru fiecare autotest.

Optimizarea cadrului pentru autotestele cu mai multe fire s-a dovedit a nu fi atât de dificilă. Cucumber 4 rulează fiecare test individual pe un fir dedicat de la început până la sfârșit, așa că unele lucruri statice comune au fost pur și simplu convertite în variabile ThreadLocal. 
Principalul lucru atunci când faceți conversie folosind instrumentele de refactorizare Idea este să verificați locurile în care a fost comparată variabila (de exemplu, verificarea null). În plus, trebuie să adăugați pluginul Allure la adnotarea clasei Junit Runner.

Exemplu de configurare a autotestelor:

 
<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>

Implementare, scalare: experiență de utilizare a testelor automate la VTBExemplu de raport Allure (cel mai instabil test, 5 reluări)

Implementare, scalare: experiență de utilizare a testelor automate la VTBÎncărcare runner în timpul testelor (8 nuclee, 8 GB RAM, 24 fire)

Pro-uri:

  • consum redus de resurse;
  • suport nativ de la Cucumber - nu sunt necesare instrumente suplimentare;
  • capacitatea de a rula mai mult de 6 fire de execuție per nucleu de procesor.

Contra:

  • trebuie să vă asigurați că codul acceptă execuția cu mai multe fire;
  • pragul de intrare crește.

Rapoarte Allure pe paginile GitLab

După introducerea execuției multi-threaded, am început să petrecem mult mai mult timp analizând rapoarte. În acel moment, trebuia să încărcăm fiecare raport ca artefact în GitLab, apoi să îl descărcam și să-l despachetăm. Nu este foarte convenabil și durează mult. Și dacă altcineva dorește să vadă singur raportul, atunci va trebui să facă aceleași operațiuni. Am vrut să primim feedback mai repede și am găsit o soluție - paginile GitLab. Aceasta este o caracteristică încorporată care este disponibilă imediat în toate versiunile recente de GitLab. Vă permite să implementați site-uri statice pe serverul dvs. și să le accesați printr-un link direct.

Toate capturile de ecran ale rapoartelor Allure au fost făcute pe paginile GitLab. Script pentru implementarea raportului în paginile GitLab - în Windows PowerShell (înainte de aceasta trebuie să rulați autotestări):

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

Cu rezultat faptul că 

Deci, dacă te gândeai dacă ai nevoie de cod Thread safe în cadrul de autotest Cucumber, acum răspunsul este evident - cu Cucumber 4 este ușor să-l implementezi, crescând astfel semnificativ numărul de fire lansate simultan. Cu această metodă de efectuare a testelor, întrebarea devine acum despre performanța mașinii cu selenoid și a bancului de testare.

Practica a arătat că rularea testelor automate pe fire vă permite să reduceți consumul de resurse la minim cu cele mai bune performanțe. După cum se poate observa din grafice, dublarea firelor nu duce la o accelerare similară în testele de performanță. Cu toate acestea, am putut adăuga peste 2 de teste automate la construirea aplicației, care chiar și cu 200 reluări rulează în aproximativ 5 de minute. Acest lucru vă permite să primiți feedback rapid de la aceștia și, dacă este necesar, să faceți modificări și să repetați procedura din nou.

Sursa: www.habr.com

Adauga un comentariu