Implementar, escalar: la experiencia de usar autotests en VTB

Nuestra división crea tuberías completamente automáticas para generar nuevas versiones de aplicaciones en el entorno de producción. Por supuesto, esto requiere pruebas funcionales automatizadas. Debajo del corte: la historia de cómo, comenzando con las pruebas en un hilo en la máquina local, llegamos al lanzamiento multiproceso de autocomprobaciones en Selenoid en la tubería de ensamblaje con el informe Allure en las páginas de GitLab y, como resultado, obtuvimos una herramienta de automatización genial que los futuros pueden usar equipos



Por donde empezamos


Para implementar las pruebas automáticas e integrarlas en la tubería, necesitábamos un marco para la automatización, que se pueda cambiar de manera flexible para satisfacer nuestras necesidades. Idealmente, quería obtener un estándar único para el motor de prueba automática, adaptado para incrustar pruebas automáticas en una tubería. Para la implementación, hemos elegido las siguientes tecnologías:

  • Java
  • Maven
  • Selenio
  • Pepino + JUNIT 4,
  • Encanto
  • Gitlab



¿Por qué tal conjunto? Java es uno de los idiomas más populares para las pruebas automáticas, además, todos los miembros del equipo lo hablan. El selenio es la solución obvia. Se suponía que el pepino, entre otras cosas, aumentaría la confianza en los resultados de las pruebas automáticas de las unidades involucradas en las pruebas manuales.

Pruebas de rosca simple


Para no reinventar la rueda, tomamos los desarrollos de varios repositorios en GitHub como la base del marco y los adaptamos para nosotros. Creamos un repositorio para la biblioteca principal con el núcleo del marco de autotest y un repositorio con un ejemplo Gold de implementación de autotests en nuestro núcleo. Cada equipo tuvo que tomar una imagen dorada y desarrollar pruebas en ella, adaptándola a su proyecto. Implementamos en el banco GitLab-CI, en el que configuramos:

  • ejecuciones diarias de todas las pruebas automáticas escritas para cada proyecto;
  • se lanza en la tubería de montaje.

Al principio hubo pocas pruebas, y fueron en una secuencia. El lanzamiento de un solo subproceso en el GitLab Windows-runner fue bastante satisfactorio para nosotros: las pruebas cargaron ligeramente el banco de pruebas y casi no utilizaron recursos.

Con el tiempo, las pruebas automáticas se hicieron más y más, y pensamos en ejecutarlas en paralelo, cuando una carrera completa comenzó a tomar aproximadamente tres horas. Hubo otros problemas:

  • no pudimos asegurarnos de que las pruebas sean estables;
  • las pruebas que pasaron por varias ejecuciones seguidas en la máquina local a veces cayeron en CI.

Ejemplo de configuración de prueba automática:

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


Ejemplo de informe de Allure


Carga del corredor durante las pruebas (8 núcleos, 8 GB de RAM, 1 hilo)

Ventajas de las pruebas de un solo subproceso:

  • fácil de configurar y ejecutar;
  • Los lanzamientos en CI prácticamente no difieren de los lanzamientos locales;
  • las pruebas no se afectan entre sí;
  • requisitos mínimos de recursos del corredor.

Contras de las pruebas de subproceso único:

  • muy largo plazo;
  • larga estabilización de pruebas;
  • uso ineficiente de los recursos del corredor, utilización extremadamente baja.

Pruebas de horquilla JVM


Como no nos importaba el código seguro para subprocesos al implementar el marco básico, el complemento cucumber-jvm-parallel- for para Maven se convirtió en la forma más obvia de ejecutarse en paralelo. El complemento es fácil de configurar, pero para el correcto funcionamiento paralelo de las pruebas automáticas, debe ejecutarse en navegadores separados. Nada que hacer, tuve que usar Selenoid.

El servidor Selenoid se creó en una máquina con 32 núcleos y 24 GB de RAM. El límite se estableció en 48 navegadores: 1.5 subprocesos por núcleo y aproximadamente 400 MB de RAM. Como resultado, el tiempo de prueba se redujo de tres horas a 40 minutos. Acelerar las ejecuciones ayudó a resolver el problema de estabilización: ahora podríamos ejecutar rápidamente nuevas pruebas automáticas de 20 a 30 veces hasta que nos aseguremos de que se realicen de manera estable.
El primer inconveniente de la solución fue la alta utilización de los recursos del corredor con un pequeño número de subprocesos paralelos: en 4 núcleos y 8 GB de RAM, las pruebas funcionaron de manera estable en no más de 6 subprocesos. El segundo inconveniente: el complemento genera clases de corredor para cada escenario, sin importar cuántas se ejecuten.

Importante! No arroje una variable con etiquetas en argLine , por ejemplo, así:

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

Si pasa la etiqueta de esta manera, el complemento generará corredores para todas las pruebas, es decir, intente ejecutar todas las pruebas, omitiéndolas justo después del lanzamiento y creando muchas horquillas JVM.

Es correcto lanzar la variable con la etiqueta en las etiquetas en la configuración del complemento, vea el ejemplo a continuación. Otros métodos que probamos tienen problemas para conectar el complemento Allure.

Ejemplo de tiempo de ejecución para 6 pruebas cortas con configuraciones incorrectas:

 [INFO] Total time: 03:17 min 

Un ejemplo de tiempo de ejecución de prueba si pasa directamente la etiqueta a mvn ... –Dcucumber.options :

 [INFO] Total time: 44.467 s 

Ejemplo de configuración de prueba automática:

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


Un ejemplo de un informe Allure (la prueba más inestable, 4 rerana)

Carga del corredor durante las pruebas (8 núcleos, 8 GB de RAM, 12 hilos)

Pros:

  • configuración simple: solo necesita agregar el complemento;
  • la capacidad de realizar simultáneamente una gran cantidad de pruebas;
  • estabilización más rápida de las pruebas gracias a la reivindicación 1.

Contras:

  • Se requieren múltiples OS / contenedores;
  • alto consumo de recursos por tenedor;
  • El complemento está en desuso y ya no es compatible.

Cómo vencer la inestabilidad


Los bancos de pruebas no son perfectos, como lo son las pruebas automáticas en sí. Como era de esperar, obtuvimos una serie de pruebas frágiles. El complemento Maven Surefire vino al rescate , que de inmediato admite el reinicio de las pruebas caídas. Debe actualizar la versión del complemento a al menos 2.21 y escribir una línea con el número de reinicios en el archivo pom o pasar como argumento para Maven.

Ejemplo de configuración de prueba automática:

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

O al inicio: mvn ... -Dsurefire.rerunFailingTestsCount = 2 ...
Alternativamente, configure las opciones de Maven para el script de PowerShell (PS1):

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

Pros:

  • no es necesario perder el tiempo analizando una prueba inestable cuando falla;
  • Puede suavizar los problemas de estabilidad del banco de pruebas.

Contras:

  • puede omitir defectos flotantes;
  • el tiempo de ejecución aumenta.

Pruebas paralelas con la biblioteca de Pepino 4



El número de pruebas creció todos los días. Pensamos nuevamente en acelerar las carreras. Además, quería integrar tantas pruebas como sea posible en el ensamblaje de la tubería de la aplicación. Un factor crítico fue la generación demasiado larga de corredores cuando se ejecutaba en paralelo con el complemento Maven.

Cucumber 4 ya se lanzó en ese momento, por lo que decidimos reescribir el kernel para esta versión. En las notas de la versión, se nos prometió un lanzamiento paralelo a nivel de hilo. Teóricamente, esto debería haber sido:

  • acelerar significativamente la ejecución de las pruebas automáticas al aumentar el número de subprocesos;
  • excluir la pérdida de tiempo para generar corredores para cada autotest.

Optimizar el marco para las pruebas automáticas de subprocesos múltiples no fue tan difícil. Cucumber 4 ejecuta cada prueba individual en un hilo dedicado de principio a fin, por lo que algunas cosas estáticas comunes simplemente se convirtieron en variables ThreadLocal.
Lo principal al convertir con las herramientas de refactorización de Idea es verificar los lugares donde se comparó la variable (por ejemplo, verificar nulo). Además, debe representar el complemento Allure en las anotaciones de la clase Junit Runner.

Ejemplo de configuración de prueba automática:

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

Un ejemplo de un informe Allure (la prueba más inestable, 5 vueltas)

Carga del corredor durante las pruebas (8 núcleos, 8 GB de RAM, 24 hilos)

Pros:

  • bajo consumo de recursos;
  • soporte nativo de Cucumber: no se necesitan herramientas adicionales;
  • La capacidad de ejecutar más de 6 subprocesos en el núcleo del procesador.

Contras:

  • debe asegurarse de que el código admita la ejecución de subprocesos múltiples;
  • El umbral de entrada aumenta.

Informes de Allure en páginas de GitLab


Después de la introducción del lanzamiento multiproceso, comenzamos a dedicar mucho más tiempo a analizar informes. En ese momento, tuvimos que cargar cada informe como un artefacto en GitLab, luego descargarlo, desempaquetarlo. No es muy conveniente y largo. Y si alguien más quiere ver el informe en casa, deberá realizar las mismas operaciones. Queríamos recibir comentarios más rápido, y había una salida: las páginas de GitLab. Esta es una característica incorporada que está disponible de fábrica en todas las versiones recientes de GitLab. Le permite implementar sitios estáticos en su servidor y acceder a ellos a través de un enlace directo.

Todas las capturas de pantalla con informes de Allure se hicieron en páginas de GitLab. El script para implementar el informe en las páginas de GitLab es en Windows PowerShell (antes de eso, debe ejecutar las pruebas automáticas):

 New-Item -ItemType directory -Path $testresult\history | 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 $buildlocation\target\site\allure-maven-plugin\* $buildlocation\public /s /i /Y 

Cual es el resultado


Entonces, si estaba pensando si necesita un código seguro para subprocesos en el marco de prueba automática de Cucumber, ahora la respuesta es obvia: con Cucumber 4 es fácil de implementar, lo que aumenta significativamente la cantidad de subprocesos lanzados simultáneamente. Con este método de ejecución de pruebas, la pregunta ya es sobre el rendimiento de la máquina con Selenoid y el banco de pruebas.

La práctica ha demostrado que ejecutar pruebas automáticas en subprocesos puede minimizar el consumo de recursos con el mejor rendimiento. Como se puede ver en los gráficos, un aumento de 2 veces en los flujos no conduce a una aceleración similar al pasar las pruebas de rendimiento. Sin embargo, pudimos agregar más de 200 pruebas automáticas al ensamblaje de la aplicación, que incluso con 5 rerans pueden completarse en aproximadamente 24 minutos. Esto le permite recibir comentarios rápidos de ellos y, si es necesario, realizar cambios y repetir el procedimiento nuevamente.

Source: https://habr.com/ru/post/473950/


All Articles