Integración de pruebas Cypress con Docker, Buildkite y CICD #frontend@twiliosendgrid
Publicado: 2020-12-30Hemos escrito muchas pruebas de Cypress de extremo a extremo (E2E) para validar que nuestras aplicaciones web siguen funcionando como se esperaba con el backend. Después de escribir estas pruebas de automatización del navegador, nos gustaría que estas pruebas de Cypress siempre se ejecuten o se activen de alguna manera como nuestras pruebas unitarias antes de fusionar el código e implementarlo en ciertos entornos. Esto nos llevó por el camino de querer ejecutar nuestras pruebas de Cypress en un contenedor Docker para integrarnos con nuestro proveedor de integración continua (CI) y las máquinas que usamos en la nube para ejecutar estos contenedores.
Cuando se trata de flujos de implementación, usamos Buildkite como nuestro proveedor de CI. Esto nos permite generar una compilación de pasos automatizados para nuestra aplicación en una canalización de Buildkite cuando planeamos mover el código en todos los ámbitos. Para obtener más contexto, una canalización es un lugar generalmente vinculado al repositorio de una aplicación donde podemos ver compilaciones o desencadenar compilaciones con ciertos pasos para ejecutar cuando crea solicitudes de incorporación de cambios, envía nuevos cambios de código, fusiona código para dominar e implementa en diferentes entornos. . Creamos múltiples canalizaciones para propósitos separados, como implementación, pruebas de Cypress activadas y pruebas de Cypress específicas que se ejecutan según un cronograma.
Esta publicación de blog asume que ya ha escrito pruebas de Cypress antes y tiene algunas pruebas en ejecución, pero le gustaría tener ideas sobre cómo ejecutar estas pruebas todo el tiempo en sus flujos de desarrollo e implementación. Si desea obtener más información general sobre cómo escribir pruebas de Cypress, puede consultar esta publicación de blog anterior y luego volver a visitarla cuando tenga algo que ejecutar.
Nuestro objetivo es guiarlo a través de ideas sobre cómo puede integrar las pruebas de Cypress en un contenedor de Docker con su proveedor de CI al observar cómo lo hemos hecho con Docker Compose y Buildkite en nuestra canalización de implementación. Estas ideas se pueden ampliar en su infraestructura para que las estrategias, los comandos y las variables de entorno se apliquen al activar las pruebas de Cypress.
Nuestro flujo CICD estándar
En nuestro flujo de implementación y desarrollo estándar, configuramos dos canalizaciones:
- El primero maneja nuestros pasos de implementación para cuando insertamos el código.
- El segundo activa nuestras pruebas de Cypress para que se ejecuten en paralelo y se registren. El éxito o el fracaso de esto afecta la canalización de implementación.
En nuestra canalización de implementación, construimos nuestros activos de aplicaciones web, ejecutamos pruebas unitarias y tenemos pasos para activar pruebas de Cypress seleccionadas antes de implementarlas en cada entorno. Nos aseguramos de que pasen antes de desactivar la capacidad de hacer un despliegue de botón. Estas pruebas desencadenadas de Cypress en la segunda canalización también se ejecutan en un contenedor de Docker y están conectadas al tablero de Cypress pagado a través de una clave de grabación para que podamos ver los videos, las capturas de pantalla y la salida de la consola de esas pruebas de Cypress para depurar cualquier problema.
Usando las entradas de selección de Buildkite , ideamos una dinámica, elija su propia aventura para que los usuarios pudieran seleccionar "Sí" o "No" para decidir qué carpetas de especificaciones de Cypress ejecutar y verificar a medida que impulsamos más código. La respuesta predeterminada sería "No" para todas las opciones, pero el valor de "Sí" sería la ruta global a la carpeta de especificaciones de Cypress.
A veces, no queremos ejecutar todas las pruebas de Cypress si nuestro cambio de código no afecta a otras páginas. En cambio, solo queremos activar las pruebas que sabemos que se verán afectadas. Es posible que también debamos implementar una solución rápida en producción para un problema de error urgente, ya que nos sentimos lo suficientemente seguros como para no ejecutar nuestras pruebas de Cypress, que pueden demorar entre 0 y 10 minutos, según la cantidad de pruebas que activemos. Proporcionamos un ejemplo tanto visualmente como en los pasos de YML para esta parte.
A continuación, implementamos nuestro propio script de Bash llamado runCypress.sh
para que se ejecute después de ese paso de selección para analizar los valores "Sí" o "No" seleccionados. Hacemos esto para formar una lista de rutas de especificación separadas por comas para ejecutar y agregar como una opción, --spec
, a nuestro eventual comando Cypress que se ejecuta en un contenedor Docker en una canalización desencadenada. Exportamos variables de entorno, como la lista formada de especificaciones en "CYPRESS_SPECS" y el entorno de prueba actual en "CYPRESS_TEST_ENV" para usar en la canalización que estamos activando al final del script con buildkite-agent pipeline upload "$DIRNAME"/triggerCypress.yml
.
Es posible que haya notado cómo también exportamos una variable de entorno "ASYNC". En Buildkite, puede elegir que un paso de compilación desencadenado bloquee o no bloquee en términos de éxito o fracaso. Si tenemos "ASYNC" establecido en verdadero, nuestros pasos principales de canalización de implementación continuarán ejecutándose y no esperarán a que finalicen las pruebas de Cypress activadas en una canalización diferente. El éxito o el fracaso de la canalización no afecta el éxito o el fracaso de la canalización de implementación.
Si tenemos "ASYNC" establecido en falso, nuestros pasos principales de canalización de implementación se bloquearán hasta que finalicen las pruebas de Cypress activadas en una canalización diferente. El éxito o el fracaso de la compilación desencadenada conduce al éxito o al fracaso general de la canalización de implementación donde continúa.
Cuando nuestro código todavía está en una rama de características con una solicitud de extracción abierta, nos gusta impulsar más cambios, activar algunas pruebas de Cypress y ver cómo se comportan las cosas. Sin embargo, no siempre queremos bloquear el resto de los pasos de la canalización de implementación para que no se ejecuten si las pruebas desencadenadas fallan, ya que potencialmente hay más cambios en el camino. En este escenario, configuramos "ASYNC" en falso para no bloquear si las pruebas de Cypress fallan. Para el caso en el que ya fusionamos nuestra solicitud de incorporación de cambios en el maestro y la implementamos en la preparación, pero queremos activar las pruebas de Cypress antes de implementarlas en producción, configuramos "ASYNC" en verdadero, ya que queremos que las pruebas de Cypress siempre pasen antes de salir a producción. .
Volviendo a runCypress.sh
, recordamos que la secuencia de comandos desencadena la ejecución de la segunda canalización llamando al archivo triggerCypress.yml
con valores de variables de entorno asignados. El archivo triggerCypress.yml
se parece a esto. Notará que el paso de "activación" y la interpolación de valores en los mensajes de compilación son útiles para la depuración y los nombres de pasos dinámicos.
Ya sea que activemos las pruebas de Cypress para que se ejecuten desde nuestra canalización de implementación a una canalización de activación separada o ejecutemos las pruebas de Cypress según un cronograma en una canalización dedicada, seguimos y reutilizamos los mismos pasos mientras solo cambiamos los valores de las variables de entorno.
Estos pasos implican:
- Creación de la imagen de Docker con una etiqueta más reciente y una etiqueta de versión única
- Subiendo la imagen de Docker a nuestro registro privado
- Desplegar esa misma imagen para ejecutar nuestras pruebas de Cypress en función de nuestros valores de variables de entorno en un contenedor Docker
Estos pasos se describen en un archivo pipeline.cypress.yml
así:
Cuando activamos las pruebas de Cypress para que se ejecuten, iniciará una compilación separada en la tubería de activación de Cypress. Según el éxito o el fracaso de la compilación, la ejecución de prueba de Cypress bloqueará o nos permitirá realizar la implementación en producción cuando pasemos de la preparación a la producción para las compilaciones de la rama maestra.
Al hacer clic en el paso "Ciprés desencadenado/integración/...", accederá a la compilación de la canalización desencadenada con una vista como esta para ver cómo fueron las pruebas.
Si tiene curiosidad acerca de cómo está conectada la parte de Docker, nuestro Dockerfile.cypress
y docker-compose.cypress.yml
usan esas variables de entorno exportadas de nuestras canalizaciones para luego usar el comando Cypress adecuado del paquete de nuestra aplicación. package.json
apuntando a la derecha entorno de prueba y ejecutando los archivos de especificaciones seleccionados. Los fragmentos a continuación muestran nuestro enfoque general que puede ampliar y mejorar para ser más flexible.
Fuera de las pruebas ejecutadas durante nuestros ciclos habituales de integración e implementación, creamos canalizaciones dedicadas de Buildkite. Estas canalizaciones se ejecutan según un cronograma para pruebas importantes en nuestro entorno de prueba para garantizar que nuestros servicios de frontend y backend funcionen correctamente. Reutilizamos pasos de canalización similares, ajustamos ciertos valores de variables de entorno en la configuración de la canalización de Buildkite y configuramos un cronograma cron para que se ejecute a una hora programada. Esto nos ayuda a detectar muchos errores y problemas con el entorno de prueba a medida que continuamos monitoreando qué tan bien están funcionando nuestras pruebas y si algo posterior o de nuestras propias inserciones de código puede haber llevado a pruebas fallidas.
paralelización
También utilizamos el indicador de paralelización para aprovechar la cantidad de máquinas de AWS que podemos activar desde nuestra cola de agentes de compilación configurada por nuestro equipo de operaciones. Con este indicador de paralelización, Cypress genera automáticamente una cierta cantidad de máquinas en función del número que configuramos en la propiedad de "paralelismo" de Buildkite.
Pudimos ejecutar más de 200 pruebas en alrededor de 5 minutos para uno de nuestros repositorios de aplicaciones.
Luego distribuye todas las pruebas de Cypress para que se ejecuten en paralelo en esas máquinas mientras mantiene el registro de cada una de las pruebas para una ejecución de compilación específica. ¡Esto aumentó drásticamente nuestros tiempos de ejecución de prueba!
Estos son algunos consejos al paralelizar sus pruebas de Cypress:
- Siga las sugerencias en Dashboard Service para la cantidad óptima de máquinas y configure la cantidad de máquinas en una variable de entorno para flexibilidad en sus canalizaciones.
- Dividir en archivos de prueba más pequeños, especialmente dividiendo las pruebas de ejecución más largas en fragmentos que podemos paralelizar mejor entre máquinas.
- Asegúrese de que sus pruebas de Cypress estén aisladas y no se afecten entre sí ni dependan unas de otras. Cuando se trate de flujos relacionados con la actualización, la creación o la eliminación, use usuarios y recursos de datos separados para evitar que las pruebas se pisoteen entre sí y se encuentren en condiciones de carrera. Sus archivos de prueba pueden ejecutarse en cualquier orden, así que asegúrese de que no sea un problema al ejecutar todas sus pruebas.
- Para Buildkite, recuerde pasar el valor de la variable de entorno del ID de compilación de Buildkite a la
--ci-build-id
además de la opciónparallel
para que sepa con qué ejecución de compilación única asociarse al paralelizar pruebas entre máquinas.
Para revisar:
Para conectar sus pruebas de Cypress a su proveedor de IC, como Buildkite, deberá:
- Cree una imagen de Docker con el código de su aplicación, utilizando la imagen base de Cypress necesaria y las dependencias requeridas para ejecutar las pruebas en un entorno de Nodo contra ciertos navegadores.
- Empuje su imagen de Docker a un registro con ciertas etiquetas
- Tire de la misma imagen hacia abajo en un paso posterior
- Ejecute sus pruebas de Cypress en modo autónomo y con claves de grabación si está utilizando Cypress Dashboard Service.
- Establezca diferentes valores de variables de entorno y conéctelos a los comandos que ejecuta para que Cypress active las pruebas de Cypress seleccionadas en un determinado entorno de prueba en esos contenedores de Docker.
Estos pasos generales se pueden reutilizar y aplicar a las pruebas de Cypress que se ejecutan según un cronograma y otros casos de uso, como activar pruebas para que se ejecuten en navegadores seleccionados además de sus canalizaciones de implementación. La clave es aprovechar las capacidades de su proveedor de CI y configurar sus comandos para que sean flexibles y configurables en función de los valores de las variables de entorno.
Configure sus comandos para que sean flexibles y configurables en función de los valores de las variables de entorno.
Una vez que tenga sus pruebas ejecutándose en Docker con su proveedor de CI (y si paga por Dashboard Service), puede aprovechar la paralelización de sus pruebas en varias máquinas. Es posible que deba modificar las pruebas y los recursos existentes para que no dependan de otros para evitar que las pruebas se pisoteen entre sí.
También discutimos ideas que puede probar usted mismo, como crear un conjunto de pruebas para validar su API de back-end o activar pruebas para ejecutarlas en el navegador que elija. También hay más formas de configurar la integración continua aquí en los documentos de Cypress .
Además, es importante ejecutar estas pruebas de Cypress durante los flujos de implementación o los intervalos programados para asegurarse de que sus entornos de desarrollo funcionen como se espera todo el tiempo. Ha habido innumerables ocasiones en las que nuestras pruebas de Cypress detectaron problemas relacionados con los servicios de backend posteriores que estaban inactivos o cambiaron de alguna manera, lo que se manifestó en errores de aplicaciones de frontend. Especialmente nos salvaron de errores inesperados en nuestras páginas web después de que lanzamos nuevos cambios en el código de React.
Mantener las pruebas aprobadas y monitorear las ejecuciones de pruebas fallidas de manera diligente en nuestros entornos de prueba conduce a menos tickets de soporte y clientes más felices en producción. Mantener un conjunto saludable y estable de pruebas de Cypress ejecutándose cuando impulsa nuevos cambios de código brinda una mayor confianza de que las cosas funcionan bien y le recomendamos que usted y sus equipos hagan lo mismo con sus pruebas de Cypress.
Para obtener más recursos sobre las pruebas de Cypress, consulte los siguientes artículos:
- Qué considerar al escribir pruebas E2E
- Descripción general de 1,000 pies de escritura de pruebas de ciprés
- TypeScript Todas las cosas en sus pruebas de Cypress
- Manejo de flujos de correo electrónico en Cypress Tests
- Ideas para configurar, organizar y consolidar sus pruebas de Cypress