Cómo ahorrar tiempo corriendo pruebas automatizadas con máquinas de CI en paralelo[

por calpee

Las pruebas automatizadas son parte de muchos proyectos de programación, lo que garantiza que el software sea impecable. Cuanto más grande sea el proyecto, más grande puede ser la suite de pruebas, lo que puede hacer que las pruebas automatizadas tarden mucho tiempo en ejecutarse. En este artículo, aprenderá a ejecutar pruebas automatizadas más rápido con máquinas de integración continua (CI) paralelas y qué problemas se pueden encontrar. El artículo cubre problemas comunes de pruebas en paralelo, basados ​​en pruebas de Ruby y JavaScript.[

Logotipo de Knapsack ProPruebas automatizadas lentas[

Las pruebas automatizadas se pueden considerar lentas cuando los programadores dejan de ejecutar todo el conjunto de pruebas en su máquina local porque consume demasiado tiempo. La mayoría de las veces utiliza servidores de CI como Jenkins, CircleCI, Github Actions para ejecutar sus pruebas en una máquina externa en lugar de la suya. Cuando tiene un conjunto de pruebas que se ejecuta durante una hora, no es eficiente ejecutarlo en su computadora. Las pruebas de navegador de un extremo a otro para su proyecto web pueden tardar mucho en ejecutarse. La ejecución de pruebas en un servidor de CI durante una hora tampoco es eficiente. Usted, como desarrollador, necesita un ciclo de retroalimentación rápido para saber si su software funciona bien. Las pruebas automatizadas deberían ayudarlo con eso.[

Divida las pruebas entre muchas máquinas de CI para ahorrar tiempo[

Una forma de ahorrarle tiempo es hacer que CI compile lo más rápido posible. Cuando tiene pruebas que tardan, por ejemplo, 1 hora en ejecutarse, puede aprovechar la configuración de su servidor CI y configurar trabajos paralelos (máquinas / nodos CI paralelos). Cada uno de los trabajos paralelos puede ejecutar una parte del conjunto de pruebas.[

Debe dividir sus pruebas entre máquinas de CI paralelas. Cuando tiene un conjunto de pruebas de 60 minutos, puede ejecutar 20 trabajos paralelos donde cada trabajo ejecuta un pequeño conjunto de pruebas y esto debería ahorrarle tiempo. En un escenario óptimo, realizaría pruebas durante 3 minutos por trabajo.[

¿Cómo asegurarse de que cada trabajo se ejecute durante 3 minutos? Como primer paso, puede aplicar una solución sencilla. Ordene todos sus archivos de prueba alfabéticamente y divídalos por el número de trabajos paralelos. Cada uno de sus archivos de prueba puede tener un tiempo de ejecución diferente según la cantidad de casos de prueba que tenga por archivo de prueba y la complejidad de cada caso de prueba. Pero puede terminar con archivos de prueba divididos de una manera subóptima, y ​​esto es problemático. La siguiente imagen ilustra una división subóptima de pruebas entre trabajos de CI paralelos donde un trabajo ejecuta demasiadas pruebas y termina siendo un cuello de botella.[

Knapsack Pro Distribución subóptima de pruebas[
Distribución subóptima de las pruebas: la barra roja representa un nodo que tarda demasiado[

Las pruebas estáticas se dividen según el tiempo de las pruebas[

Puede utilizar el tiempo de ejecución de cada archivo de prueba para predecir cómo dividir el conjunto de pruebas entre trabajos paralelos de manera que se asegure que el tiempo empleado por cada trabajo sea similar.[

Puede usar herramientas como la gema rubí mochila de código abierto, diseñada para Ruby y sus corredores de prueba como RSpec, Minitest, Cucumber. Incluso puede realizar un seguimiento de todas sus confirmaciones y registrar el tiempo de ejecución de sus pruebas por compilación de CI con knapsack_pro gem para predecir mejor cómo su próxima compilación de CI debe distribuir las pruebas en trabajos de CI paralelos.[

La división de archivos de prueba entre trabajos paralelos según el tiempo de ejecución del archivo de prueba tiene algunas limitaciones. Por ejemplo, cuando su archivo de prueba tiene un tiempo de ejecución no determinista. Esto puede suceder cuando la prueba de su navegador de un extremo a otro necesita cargar una página web compleja y el navegador realiza muchas solicitudes a la API externa que a veces tienen una respuesta lenta. Hay muchos componentes necesarios para cargar completamente la página y esto puede afectar la velocidad del caso de prueba. A veces, una página web se carga más rápido o más lento. Esto afecta el tiempo que se tarda en ejecutar el archivo de prueba. A menudo hay un efecto compuesto y sus trabajos paralelos pueden durar mucho más de lo esperado 3 minutos, lo que puede provocar un cuello de botella que se ejecute durante demasiado tiempo y ralentice la construcción de CI.[

Otro problema común es la hora de inicio de cada trabajo paralelo. A menudo, antes de comenzar a ejecutar las pruebas, debe preparar el entorno y, para ello, debe instalar dependencias dentro del trabajo paralelo o cargar datos desde la caché. Esto puede llevar a que todos los trabajos paralelos comiencen a funcionar en diferentes momentos. En consecuencia, el trabajo paralelo que comienza en último lugar podría convertirse en un cuello de botella para toda la compilación de CI.[

Pruebas dinámicas divididas entre trabajos paralelos[

Para solucionar problemas con la división de pruebas estáticas, puede utilizar la división de pruebas dinámicas. La idea es sencilla. Tiene una lista de archivos de prueba en una cola. Luego, cada trabajo paralelo toma algunos archivos de prueba de la cola y los ejecuta. Cuando finaliza, toma otro conjunto de archivos de prueba de la cola. Esto continúa hasta que se consume toda la cola. De esta manera, si uno de los trabajos paralelos ejecuta casos de prueba lentos, simplemente terminará consumiendo menos archivos de prueba de la cola. Lo mismo sucedería con el trabajo que comenzó su trabajo tarde debido a la configuración lenta del entorno. También ejecutará menos casos de prueba.[

El siguiente gráfico muestra cómo funciona la división dinámica con la cola.[

API de Knapsack Pro[
los trabajos paralelos consumen archivos de prueba de la cola[

La división de pruebas dinámicas debería dar como resultado una división de pruebas óptima entre trabajos de CI en paralelo, como se muestra en el gráfico siguiente.[

Paquete de pruebas óptimo de Knapsack Pro[
conjunto de pruebas óptimo dividido entre trabajos paralelos[

Cómo implementar pruebas dinámicas divididas con una cola[

Si es un desarrollador de Ruby o JavaScript que utiliza Jest o Cypress para realizar pruebas, puede utilizar la herramienta Knapsack Pro para dividir sus archivos de prueba en su servidor CI. es una solución independiente de CI que funciona con cualquier proveedor de CI. A continuación, puede ver una configuración YAML de ejemplo que es similar a la configuración actual de su servidor CI.[

jobs:

 - name: Run Ruby tests with Knapsack Pro
   parallelism: 10 # run 10 parallel CI nodes
   commands:
     # Run RSpec specs in parallel
     - run: bundle exec knapsack_pro:queue:rspec
    
     # Run Minitest tests in parallel
     - run: bundle exec knapsack_pro:queue:minitest
    
     # Run Cucumber tests in parallel
     - run: bundle exec knapsack_pro:queue:cucumber
    
     # ... other Ruby test runners here


 - name: Run JS tests with Knapsack Pro
   parallelism: 4
   commands:
     # Run Cypress tests in parallel
     - $(npm bin)/knapsack-pro-cypress
    
     # Run Jest tests in parallel
     - $(npm bin)/knapsack-pro-jest

[source code can be found at https://gist.github.com/ArturT/580df4fd7852e67379e9b263228e1994#file-ci-server-config-yaml ]

Los desarrolladores de Ruby asimismo pueden hallar útil una función dedicada al ejecutor de pruebas RSpec, que descubre automáticamente los archivos de prueba pausados y los divide según las situaciones de prueba particulares. De esta manera, su archivo de prueba RSpec retardado asimismo se puede ejecutar en trabajos paralelos.[

Quisiera que le resulte útil y que consiga ahorrar tiempo en su trabajo diario usando compilaciones veloces de CI en paralelo.[

You may also like