Implementar, escalar: l'experiència d'utilitzar autotests a VTB

La nostra divisió crea pipelines totalment automàtics per llançar noves versions d'aplicacions a l'entorn de producció. Per descomptat, això requereix proves funcionals automatitzades. A sota del tall hi ha una història sobre com, començant amb les proves d'un sol fil en una màquina local, vam arribar al punt de la prova automàtica de diversos fils que s'executaven a Selenoid en el pipeline de compilació amb un informe Allure a les pàgines de GitLab i, finalment, vam obtenir una eina d'automatització fantàstica. que les persones futures puguin utilitzar els equips.

Implementar, escalar: l'experiència d'utilitzar autotests a VTB

Per on vam començar

Per implementar autotests i integrar-los al pipeline, necessitàvem un marc d'automatització que es pogués canviar de manera flexible per adaptar-se a les nostres necessitats. Idealment, volia obtenir un estàndard únic per al motor d'autotest, adaptat per incrustar autotests al pipeline. Per a la implementació hem escollit les següents tecnologies:

  • Java,
  • Maven,
  • seleni,
  • Cogombre+JUNIT 4,
  • Encant,
  • gitlab.

Implementar, escalar: l'experiència d'utilitzar autotests a VTB

Per què aquest conjunt en particular? Java és un dels llenguatges més populars per a proves automatitzades i tots els membres de l'equip el parlen. El seleni és la solució òbvia. El cogombre, entre altres coses, havia d'augmentar la confiança en els resultats de les proves automatitzades per part dels departaments implicats en les proves manuals.

Proves d'un sol fil

Per no reinventar la roda, vam agafar desenvolupaments de diversos repositoris de GitHub com a base per al marc i els vam adaptar per nosaltres mateixos. Hem creat un dipòsit per a la biblioteca principal amb el nucli del marc d'autotest i un dipòsit amb un exemple Gold d'implementació de proves automàtiques al nostre nucli. Cada equip havia d'agafar la imatge Gold i desenvolupar-hi proves, adaptant-la al seu projecte. El vam desplegar al banc GitLab-CI, on vam configurar:

  • execucions diàries de totes les proves automàtiques escrites per a cada projecte;
  • llançaments en fase de construcció.

Al principi hi havia poques proves, i es feien en un sol corrent. L'execució d'un sol fil al Windows Runner GitLab ens va anar força bé: les proves van carregar el banc de proves molt lleugerament i gairebé no van utilitzar recursos.

Amb el temps, el nombre d'autotests es va anar fent cada cop més nombroses, i vam pensar en fer-les en paral·lel, quan una prova completa va començar a durar unes tres hores. També van aparèixer altres problemes:

  • no vam poder comprovar que les proves fossin estables;
  • les proves que s'executaven diverses vegades seguides a la màquina local de vegades s'estavellaven en CI.

Exemple de configuració de proves automàtiques:

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

 Implementar, escalar: l'experiència d'utilitzar autotests a VTB
Exemple d'informe de fascinació

 Implementar, escalar: l'experiència d'utilitzar autotests a VTB
Càrrega del corredor durant les proves (8 nuclis, 8 GB de RAM, 1 fil)
 
Avantatges de les proves d'un sol fil:

  • fàcil de configurar i executar;
  • els llançaments a CI pràcticament no són diferents dels llançaments locals;
  • les proves no s'afecten mútuament;
  • requisits mínims per als recursos del corredor.

Desavantatges de les proves d'un sol fil:

  • triga molt a completar-se;
  • llarga estabilització de les proves;
  • ús ineficient dels recursos del corredor, utilització extremadament baixa.

Proves a les forquilles JVM

Com que no ens vam ocupar del codi segur per a fils en implementar el marc base, la manera més òbvia d'executar-se en paral·lel era cogombre-jvm-connector-paral·lel per a Maven. El connector és fàcil de configurar, però per al correcte funcionament en paral·lel, les proves automàtiques s'han d'executar en navegadors separats. No hi ha res a fer, vaig haver d'utilitzar Selenoid.

El servidor Selenoid es va llançar en una màquina amb 32 nuclis i 24 GB de RAM. El límit es va establir en 48 navegadors: 1,5 fils per nucli i uns 400 MB de RAM. Com a resultat, el temps de prova es va reduir de tres hores a 40 minuts. L'acceleració de les tirades va ajudar a resoldre el problema d'estabilització: ara podríem executar ràpidament noves proves automàtiques de 20 a 30 vegades fins que estiguéssim segurs que funcionaven de manera fiable.
El primer inconvenient de la solució va ser l'alta utilització dels recursos del corredor amb un nombre reduït de fils paral·lels: en 4 nuclis i 8 GB de RAM, les proves es van executar de manera estable en no més de 6 fils. El segon inconvenient: el connector genera classes de corredor per a cada escenari, per molt que es llancin.

¡Important! No passeu una variable amb etiquetes a argLine, per exemple, així:

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

Si passeu l'etiqueta d'aquesta manera, el connector generarà corredors per a totes les proves, és a dir, intentarà executar totes les proves, saltant-les immediatament després del llançament i creant moltes bifurcacions JVM.

És correcte llançar una variable amb una etiqueta tags a la configuració del connector, vegeu l'exemple següent. Altres mètodes que hem provat tenen problemes per connectar el connector Allure.

Exemple de temps d'execució per a 6 proves curtes amb configuracions incorrectes:

[INFO] Total time: 03:17 min

Exemple de temps d'execució de la prova si transfereix directament l'etiqueta a mvn... –Dcucumber.opcions:

[INFO] Total time: 44.467 s

Exemple de configuració de proves automàtiques:

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

Implementar, escalar: l'experiència d'utilitzar autotests a VTB
Exemple d'informe Allure (la prova més inestable, 4 repeticions)

Implementar, escalar: l'experiència d'utilitzar autotests a VTBCàrrega del corredor durant les proves (8 nuclis, 8 GB de RAM, 12 fils)
 
Pros:

  • configuració fàcil: només cal afegir un connector;
  • la capacitat de realitzar simultàniament un gran nombre de proves;
  • acceleració de l'estabilització de la prova gràcies al pas 1. 

Contres:

  • Es requereixen diversos sistemes operatius/contenidors;
  • alt consum de recursos per a cada forquilla;
  • El connector està obsolet i ja no és compatible. 

Com superar la inestabilitat 

Els bancs de proves no són ideals, igual que els mateixos autotests. No és d'estranyar que tinguem una sèrie de proves flacky. Va venir al rescat connector de maven surefire, que de manera immediata admet reiniciar proves fallides. Heu d'actualitzar la versió del connector com a mínim a 2.21 i escriure una línia amb el nombre de reinicis al fitxer pom o passar-la com a argument a Maven.

Exemple de configuració de proves automàtiques:

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

O a l'inici: mvn... -Dsurefire.rerunFailingTestsCount=2...
Com a opció, configureu les opcions de Maven per a l'script de PowerShell (PS1):

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

Pros:

  • no cal perdre temps analitzant una prova inestable quan falla;
  • Els problemes d'estabilitat del banc de proves es poden mitigar.

Contres:

  • es poden perdre defectes flotants;
  • augmenta el temps d'execució.

Proves paral·leles amb la biblioteca Cucumber 4

El nombre de proves creixia cada dia. Vam pensar de nou a accelerar les carreres. A més, volia integrar tantes proves com fos possible al pipeline de muntatge de l'aplicació. El factor crític va ser que la generació de corredors va trigar massa quan s'executaven en paral·lel amb el connector Maven.

En aquell moment, Cucumber 4 ja s'havia llançat, així que vam decidir reescriure el nucli d'aquesta versió. A les notes de la versió se'ns va prometre un llançament paral·lel a nivell de fil. Teòricament això hauria d'haver estat:

  • accelerar significativament l'execució d'autotests augmentant el nombre de fils;
  • eliminar la pèrdua de temps en generar corredors per a cada autotest.

Optimitzar el marc per a autotests multifils no va resultar tan difícil. Cucumber 4 executa cada prova individual en un fil dedicat des del principi fins al final, de manera que algunes coses estàtiques habituals simplement es van convertir en variables ThreadLocal. 
El més important a l'hora de fer una conversió utilitzant les eines de refactorització d'Idea és comprovar els llocs on es va comparar la variable (per exemple, comprovant el null). A més, heu d'afegir el connector Allure a l'anotació de la classe Junit Runner.

Exemple de configuració de proves automàtiques:

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

Implementar, escalar: l'experiència d'utilitzar autotests a VTBExemple d'informe Allure (la prova més inestable, 5 repeticions)

Implementar, escalar: l'experiència d'utilitzar autotests a VTBCàrrega del corredor durant les proves (8 nuclis, 8 GB de RAM, 24 fils)

Pros:

  • baix consum de recursos;
  • Suport natiu de Cucumber: no calen eines addicionals;
  • la capacitat d'executar més de 6 fils per nucli de processador.

Contres:

  • heu d'assegurar-vos que el codi admet l'execució de múltiples fils;
  • augmenta el llindar d'entrada.

Informes Allure a les pàgines de GitLab

Després d'introduir l'execució multiprocés, vam començar a dedicar molt més temps a analitzar informes. En aquell moment, havíem de carregar cada informe com a artefacte a GitLab, després descarregar-lo i descomprimir-lo. No és molt còmode i porta molt de temps. I si algú més vol veure l'informe per si mateix, haurà de fer les mateixes operacions. Volíem rebre comentaris més ràpidament i vam trobar una solució: les pàgines de GitLab. Aquesta és una funció integrada que està disponible de manera immediata a totes les versions recents de GitLab. Us permet desplegar llocs estàtics al vostre servidor i accedir-hi mitjançant un enllaç directe.

Totes les captures de pantalla dels informes Allure es van fer a les pàgines de GitLab. Script per desplegar l'informe a les pàgines de GitLab - a Windows PowerShell (abans heu d'executar 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

Amb el resultat que 

Per tant, si estàveu pensant si necessiteu codi Thread safe al marc de prova automàtica Cucumber, ara la resposta és òbvia: amb Cucumber 4 és fàcil implementar-lo, augmentant així significativament el nombre de fils llançats simultàniament. Amb aquest mètode d'execució de proves, ara la pregunta es fa sobre el rendiment de la màquina amb Selenoid i el banc de proves.

La pràctica ha demostrat que executar autotests en fils us permet reduir el consum de recursos al mínim amb el millor rendiment. Com es pot veure als gràfics, duplicar els fils no comporta una acceleració similar en les proves de rendiment. Tanmateix, vam poder afegir més de 2 proves automatitzades a la compilació de l'aplicació, que fins i tot amb 200 repeticions s'executen en uns 5 minuts. Això us permet rebre comentaris ràpids d'ells i, si cal, fer canvis i repetir el procediment de nou.

Font: www.habr.com

Afegeix comentari