Blog

Automatización de pruebas E2E con Cypress e integración continua

En este artículo, exploramos Cypress y Cucumber para realizar pruebas automatizadas desde cero, orientadas a las prácticas de BDD (Behavior Driven Development) y CI (Continuous Integration), desde su implementación, instalación de dependencias, hasta llegar a un script automatizado.

En este artículo compartimos el resultado de la exploración realizada a Cypress, una herramienta de pruebas de software end-to-end eficiente y de fácil uso.

Revisamos sus capacidades y cobertura en función de las pruebas E2E para garantizar la calidad y la funcionalidad en diferentes entornos y escenarios, asegurando que la aplicación se comporte según lo esperado en todos los niveles de integración.

Al ejecutar pruebas directamente en el navegador y ofrecer características avanzadas como Time Travel, Cypress facilita la escritura, la depuración y la observación de pruebas para desarrolladores y equipos de calidad.

Inicialmente, se hablará sobre Cypress, en qué consisten sus componentes y cuáles son sus herramientas complementarias. Se ahondará específicamente en Cypress, mostrando cuáles son sus principales características y beneficios. Finalmente, se explicará cómo utilizar esta herramienta y sus componentes principales.

Este repositorio contiene la implementación de pruebas realizadas con Cypress y Cucumber. Está orientado a BDD y CI/CD, dado que posee la integración de un pipeline de Jenkins que permite ejecutarlas conectándose a un repositorio Git donde se encuentran las versiones de las automatizaciones.

Además, se agregaron algunos contenedores de Docker para optimizar los recursos disponibles. El sistema operativo utilizado fue Windows.

¿Qué es Cypress? ¿Cómo funciona?

Cypress es una herramienta de automatización de pruebas de software open source que permite escribir pruebas E2E para aplicaciones web. Es una herramienta rápida, fácil de aprender y de usar, diseñada para ser empleada por desarrolladores y equipos de calidad.

La herramienta funciona ejecutando sus pruebas dentro de un navegador web, lo que permite visualizar cómo luce y se comporta la aplicación en tiempo real. Esto hace que resulte sencillo identificar problemas y solucionarlos rápidamente.

También admite una variedad de características que la hacen ideal para la automatización de pruebas, como la captura de pantalla automática, el registro de la consola y la grabación de videos.

Características de Cypress

Entre los principales atributos de Cypress se pueden destacar los siguientes:

  • Pruebas en Tiempo Real: Cypress permite ver pruebas que se ejecutan en tiempo real en el navegador facilitando la depuración.
  • Time Travel: Cypress toma instantáneas a medida que se ejecutan las pruebas, permitiéndote volver en el tiempo y ver cómo estaba el DOM en diferentes puntos.
  • Interacción de Usuario Simulada: Puedes escribir pruebas que simulan la interacción real del usuario, como clics, desplazamientos, teclas, etc.
  • Integración Continua: Cypress es adecuada tanto para el desarrollo local como para la integración continua, facilitando la configuración de pruebas en diferentes entornos.

¿Cómo utilizar Cypress?

  • Instalación: Cypress se puede instalar fácilmente a través de npm o yarn. A menudo se instala como una dependencia de desarrollo en un proyecto.
  • Escritura de Pruebas: Las pruebas se escriben usando una sintaxis que es similar a Mocha y Chai. Puedes escribir pruebas utilizando JavaScript.
  • Ejecución de Pruebas: Puedes ejecutar pruebas en tu navegador local durante el desarrollo o en un servidor de integración continua. Cypress dispone de un panel de control donde puedes ver las pruebas que se ejecutan en tiempo real.
  • Aserciones: Cypress utiliza una variedad de aserciones para verificar que tu aplicación está funcionando correctamente. Puedes probar elementos específicos del DOM, realizar llamadas de red, revisar cookies y mucho más.

Requisitos técnicos

  • NodeJS: Se puede descargar desde aquí. Para su instalación solo basta con descargar el archivo ejecutable y seguir los pasos que indica el wizard. Verificar la instalación correcta ejecutando los siguientes comandos en una terminal: node -v y npm -v
  • Git: Se puede descargar desde esta ruta.
  • VSCode: Se puede usar cualquier IDE de preferencia, pero para el desarrollo de este proyecto fue el que se utilizó y recomienda.  Se puede descargar desde aquí.
  • Docker: Descargar desde acá e instalar siguiendo el wizard.

Automatización de Pruebas con Cypress

Para comenzar la automatización con Cypress debes seguir los siguientes pasos:

  1. Descargar o clonar el repositorio con el proyecto desde aquí. Este repositorio debe ser guardado en una carpeta creada previamente para nuestra automatización.
  2. A continuación, abrir el proyecto en VSCode y ejecutar npm install desde la terminal del IDE. Esto instalará las dependencias de desarrollo cargadas en el proyecto. Sugiero verificar que tenemos las siguientes dependencias en nuestro archivo package.json. 

En caso de no tener alguna de las dependencias, estos son los instaladores que deben ser ejecutados en una terminal desde el directorio raiz:

npm install cypress –save-dev

npm i -D cypress @bahmutov/cypress-esbuild-preprocessor esbuild

npm install @badeball/cypress-cucumber-preprocessor —-save-dev 

3. Luego, verificar que tenemos el siguiente script en nuestro package.json: “cypress:open”: “cypress open”. En caso de no existir, agregarlo debajo de scripts. Ejecutar desde la terminal npm run cypress:open

En este punto, se debe levantar el runner de Cypress donde podremos ver nuestros spec y ejecutar las pruebas en modo GUI (interfaz gráfica de usuario). Después, seleccionar “E2E Testing” y posteriormente el navegador de preferencias (se recomienda Chrome). Inmediatamente, se generará una vista como esta:

4. Luego, hacer clic en el spec cart.feature y verificar la ejecución de las pruebas. Al finalizar, ejecutar por consola node .\cucumber-html-report.js para generar el reporte.

Integración de Cypress con Docker

Docker es una plataforma open source que permite a los desarrolladores y administradores de sistemas construir, empaquetar y ejecutar aplicaciones como contenedores ligeros y autónomos. Estos contenedores pueden funcionar en cualquier entorno que tenga instalado Docker, lo que elimina los problemas de inconsistencia al mover código entre diferentes etapas del ciclo de desarrollo. Esto conlleva un desarrollo más rápido, pruebas más consistentes y despliegues más fiables.

Esta integración permite crear un entorno de desarrollo con los componentes y dependencias necesarios para los proyectos, sin necesidad de realizar instalaciones de manera local. Con esto logramos optimizar tiempos y recursos. Ahora, mostraré un ejemplo de cómo ejecutar nuestros tests en un contenedor de Docker.

Dentro del proyecto, en el directorio raíz, existe un archivo llamado Dockerfile. Este contiene las instrucciones para crear el contenedor con todas las dependencias necesarias para ejecutar las pruebas automatizadas con Cypress.

En la línea FROM está la instrucción con la imagen de Docker que vamos a utilizar. En nuestro caso, estamos empleando la última versión de Cypress/browser, sin embargo, esta puede ser cambiada por cualquiera de las disponibles.

Para este caso en específico, se podrían usar también, imágenes de Cypress/included. Toda esta información se encuentra disponible aquí.

Para crear el contenedor ejecutamos la siguiente instrucción: “docker build -t <nombre_contenedor:version>”. La variable nombre_contenedor:version es inventada para identificar nuestro contenedor. Un ejemplo podría ser: “docker build -t cypressproject:1.0”.

Una vez creada, deberíamos ver la imagen creada en nuestro Docker:

Una vez realizado este paso, solo nos queda ejecutar nuestras pruebas en nuestro contenedor con la siguiente instrucción en nuestro terminal: docker run -i -t cucumberproject:1.0 cypress run –spec cypress/e2e/features/* –browser chrome

Algunos comandos útiles a tener presente en Docker son los siguientes:

  • docker ps: Muestra todos los contenedores en ejecución. 
  • docker images: Lista todas las imágenes descargadas en tu sistema. 
  • docker stop: Detiene uno o más contenedores en ejecución. Ejemplo: docker stop container_id 
  • docker rm: Elimina uno o más contenedores. Ejemplo: docker rm container_id 
  • docker exec: Ejecuta un comando dentro de un contenedor en ejecución. Ejemplo: docker exec -it container_id bash 
  • docker logs: Muestra los registros de un contenedor en ejecución. Ejemplo: docker logs container_id 

Para obtener mayor información de los comandos de Docker, pincha aquí.

Integración con Jenkins en Docker

Jenkins nos permite realizar la construcción, prueba y despliegue continuo de nuestros proyectos.  En este apartado veremos como crear un pipeline que nos permita ejecutar pruebas sobre el proyecto, tomando como base el contenido de las pruebas de un repositorio Git.  Pedemos utilizar Jenkins instalado de manera local, como tambien integrado con Docker.  Este último será nuestro caso.  Para esto, hacemos lo siguiente:

  1. Ingresamos al dockerhub y en el buscador ingresamos “jenkins/jenkins” y presionamos buscar.
  2. Seleccionamos el primero que nos aparece en el listado

3. Podemos utilizar cualquiera de las dos versiones que nos aparecen desplegadas. Para este proyecto, se usó la versión lts. Solo debemos la instrucción que nos aparece indicada y la ejecutamos desde una terminal. Se creará automáticamente la imagen en nuestro contenedor

4. Ejecutamos el contenedor recién creado con la instrucción: docker run -d –name jenkins -p 8080:8080 -p 50000:50000 -v jenkins_home:/var/jenkins_home jenkins/jenkins:lts-jdk11. El primer puerto indicado en esta sentencias (-p 8080:8080), a través del cual nos podremos conectar a Jenkins desde nuestro local al contenedor. Podemos verificar el último contenedor creado con docker ps -l:

5. Abrimos el navegador e ingresamos en la URL: localhost:8080. Debemos ver una vista como la siguiente para configurar las credenciales de acceso:

6. Copiamos la dirección que aparece en pantalla y ejecutamos la siguiente instrucción en consola: docker exec jenkins cat /var/jenkins_home/secrets/initialAdminPassword

7. Esta instrucción nos mostrará una password por pantalla, la cual copiamos y pegamos en el campo de texto de Administrator password.

8. Instalar plugins sugeridos y darle continuar.

9. Seguimos los pasos sugeridos hasta finalizar.

Una vez terminado este proceso, ya tenemos jenkins listo para poder crear nuestro pipeline.

Creación de pipeline y ejecución de pruebas automatizadas

Ahora que ya tenemos Jenkins configurado, procedemos a crear nuestro pipeline para la ejecución de pruebas. Para esto es importante tener nuestro proyecto en algún repositorio Git. Esto porque simularemos un proyecto real de CI/CD para ejecución de pruebas automáticas con un pipeline básico que posteriormente se puede parametrizar y personalizar.

Este proceso tiene dos partes: la primera es la creación de la “cáscara” del pipeline en Jenkins y la segunda es la carga de su configuración desde un archivo Jenkinsfile que está en la raíz de nuestro proyecto. Seguimos estos pasos:

  1. Una vez dentro de Jenkins, seleccionamos Nueva Tarea > Ingresamos un nombre > Seleccionamos Pipeline > Presionamos OK.
  2. Nos dirigimos a la sección de Pipeline y seleccionamos “Pipeline script from SCM” para cargar un pipeline mediante nuestro repositorio GIT 
  3. En SCM seleccionamos GIT y ponemos la ruta de nuestro repositorio. En branch ingresamos la rama donde se ubicara nuestro repositorio, en nuestro caso está en la rama master.

4. En Script Path hay que especificar la ruta donde crearemos nuestro Jenkinsfile.  Este lo creamos en la misma ruta donde tenemos nuestro package.json de nuestro proyecto, por lo que en este campo solo debemos escribir Jenkinsfile y guardamos.

Nuestro Jenkinsfile:

Algunas consideraciones

  • Se recomienda instalar el plugin AnsiColor, el cual nos permitirá tener una mejor visualización de los logs.  Para esto ir al panel de control de Jenkins > Administrar Jenkins > Plugins > Available Plugins > AnsiColor.  Si no lo vas a instalar, elimina la línea “ansiColor(‘xterm’)” del Jenkinsfile. 
  • Nuestro Jenkinsfile tiene 3 stages: el primero simula una etapa de construcción de nuestro software, el segundo la etapa de testing y el último la etapa de desarrollo.  Esto solamente con el objetivo de mostrar cómo se vería entorno de desarrollo y pruebas parecido al real, sin embargo, el primero y último stage solo imprimen mensajes.
  • Recuerda que vamos a hacer la conexión entre nuestra “cáscara” y la configuración del archivo Jenkinsfile, por lo que es importante que en este punto ya tengas cargado el archivo en el repositorio Git en el cual haremos la conexión.

5. Ir al pipeline creado en Jenkins y darle Build. La primera vez va a fallar porque va a configurar los parámetros que generamos previamente en el Jenkinsfile. Cuando esto finalice, el botón Build nos cambiará a Build with Parameters.

6. Darle clic a Build with Parameters. Si todo va bien, nos preguntará por los spec a ejecutar y en qué browser queremos la ejecución (escoger el browser Electron).

7. Le damos clic a Ejecutar y listo. Se mostrará el pipeline ejecutando con las distintas columnas de ejecución correspondiente a nuestros stages.

Algunas consideraciones

El contenedor de Jenkins que tenemos levantado trae por defecto solo el navegador Electron y está levantado con un SO de Linux, por lo que si queremos usar otro navegador, debemos instalarlo nosotros.  Para esto debemos escribir en consola docker exec -u 0 -it jenkins bash.  Esto nos abrirá una consola dentro de nuestro contenedor y ejecutamos las siguientes instrucciones para instalar Chrome:

  • apt update
  • apt install wget
  • wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
  • apt install ./google-chrome-stable_current_amd64.deb

Con esto ya podemos ejecutar nuestras pruebas en Chrome. Deben repetirse los mismos pasos si deseas utilizar otro navegador como Firefox, por ejemplo.

Conclusiones generales

Este proyecto fue levantado y creado prácticamente desde 0, por lo que me encontré con algunas dificultades durante el proceso que documento a continuación, para tenerlo que consideración por si llegas a tener algunos de estos inconvenientes.

  1. Si al ejecutar las pruebas en el test runner de Cypress y este no carga la página, pero si lo hace desde el Chrome de escritorio, lo que se recomienda es ingresar a las opciones de desarrollador y verificar en consola el error.  En mi caso el antivirus estaba bloqueando la carga de la página, por lo que se recomienda desactivarlo en el momento de ejecutar las pruebas. 
  2. Si al ejecutar el pipeline de Jenkins, en el log muestra un error del tipo npm: not found, es porque se debe instalar Node en el contenedor. Esto lo hacemos de la siguiente forma:
  • docker exec -u 0 -it jenkins bash 
  • apt-update
  • apt install curl
  • curl -sL https://deb.nodesource.com/setup_18.x -o nodesource_setup.sh

Al momento de realizar este tutorial, la última versión de Node era la 18, pero para verificar, sugiero visitar esta página y revisar la última versión publicada, para instalar la última estable. Solo basta con poner los dos primeros dígitos donde dice “setup_XX.x” (se deben cambiar las X en mayúscula) .

  • bash nodesource_setup.sh
  • apt install nodejs
  • exit
  1. Si al ejecutar el pipeline en jenkins aparece un error con xvfb, se debe hacer lo siguiente: 
  • docker exec -u 0 -it jenkins bash 
  • apt-update
  • apt-get install xvfb
  1. Puede que al ejecutar el pipeline, aparezcan errores con algunas librerías faltantes dentro del contenedor. Para esto, ejecutamos docker exec -u 0 -it jenkins bash y las vamos instalando una a una. A continuación te dejo algunas opciones posibles y su instalador correspondiente:
LibreríaInstalador
libgtk-3-0apt-get install libgtk-3-0
libcups.so.2apt-get install libcups2
libglib2.0-0apt-get install libglib2.0-dev
libnss3.soapt-get install libnss3
libatk1.0-0apt-get install libatk1.0-0
libatk-bridge-2.0.so.0apt-get install libatk-bridge2.0-0
libgbm.so.1apt-get install libgbm-dev
libasound.so.2apt-get install libasound2
179 / 208