Pruebas e2e listas para CI para Angular con Cypress y TypeScript en menos de 60 minutos

Este artículo pretende describir cómo puedes configurar pruebas de extremo a extremo para Angular con Cypress incluyendo TypeScript. Escribirás tus primeras pruebas e2e y las prepararás para que se ejecuten en un CircleCI como sistema de integración continua con cada actualización de tu repositorio.

Las pruebas de extremo a extremo (abreviado e2e) son un tipo de prueba de software que valida el sistema de software junto con su integración con interfaces externas. El propósito de la prueba de extremo a extremo es ejercitar un escenario completo similar al de producción.

Fuente: https://www.guru99.com/end-to-end-testing.html.

Descripción

  • ¿Qué es Cypress?
  • Requisitos previos
  • Configuración de Cypress
  • Escribir algunas pruebas
  • Configuración de la integración continua
  • Conclusión y referencias

Tengo experiencia en el desarrollo de frontend en Microsoft .NET & WPF y recuerdo los tiempos en los que evaluábamos costosos frameworks para escribir pruebas de extremo a extremo para nuestros proyectos. Después de un montón de evaluaciones y semanas, incluso meses de código de cola personalizado y el desarrollo de infraestructuras de prueba en la parte superior de las herramientas existentes, finalmente conseguimos algunas pruebas e2e corriendo. Eran frágiles, a menudo fallaban debido a los ajustes manuales que teníamos que hacer o a los problemas con los corredores defectuosos en la tubería de integración continua.

Algunos años más tarde, con Angular y Protractor por defecto para las pruebas e2e, seguíamos basándonos en objetos de página, Selenium Web Driver y las pruebas seguían siendo bastante poco fiables. No se necesitaban costosos frameworks comerciales ni infraestructura personalizada. Pero, ¿era divertido escribir pruebas e2e? No.

Sin embargo ahora estamos en 2020 y ha llegado el momento de que surjan nuevos héroes. 🚀

¿Qué es Cypress?

Cypress promete pruebas rápidas, fáciles y fiables para cualquier cosa que se ejecute en un navegador. No se basa en Selenium Web Driver, que utiliza conexiones de red para interactuar con el navegador. En su lugar, Cypress es un corredor de pruebas que se ejecuta dentro de su navegador junto a su aplicación web y por lo tanto tiene un control directo sobre ella.

Sin entrar en todos los detalles, esto no sólo hace que Cypress sea más rápido y fiable, sino que también abre la puerta a un montón de otras características interesantes como

  • depuración de viajes en el tiempo,
  • facilidad en la toma de instantáneas y la grabación,
  • esperas automáticas.

Además de todas las características, Cypress tiene una experiencia de desarrollador (DX) que es casi inigualable. ¿Has visto alguna vez un mensaje en los registros de error de tu compilación fallida que te dice exactamente lo que has hecho mal, te indica las dependencias correctas que debes añadir y también enlaza con un sitio de documentación explicativa que describe el problema? Así es como se siente Cypress. Está construido por desarrolladores para desarrolladores.

Error de Cypress en el servidor de construcción diciéndote cómo solucionarlo

A continuación, instalaremos Cypress para un proyecto fresco de Angular creado con el CLI. Escribiremos algunas pruebas e2e y concluiremos con la ejecución de estas por un sistema de construcción automatizado. Todos estos pasos no deberían llevar más de 60 minutos. Tratamos de mantener los pasos tan cortos como sea posible, aprovechando las herramientas existentes como Angular Schematics, bibliotecas y plantillas comunes.

Prerrequisitos

Esta guía asume que tienes un proyecto de aplicación Angular 9 estándar. Si no es así, puedes crear uno como lo harías normalmente con la CLI de Angular. Si no tienes la CLI instalada globalmente, puedes hacer uso del comando npx que la instalará temporalmente sobre la marcha:

npx @angular/cli new <app-name>

Configurar Cypress

Para configurar Cypress junto con TypeScript lo más rápido posible, hacemos uso de un esquema existente desarrollado por BrieBug.

En la raíz de tu proyecto Angular, puedes abrir el terminal e introducir el siguiente comando:

ng add @briebug/cypress-schematic --addCypressTestScripts

Si el CLI no está instalado globalmente, el comando ng puede no estar disponible directamente. Puede forzar el uso del ng local desde el package.json:

npm run ng -- add @briebug/cypress-schematic # In case 'ng' could not be found

Podemos eliminar Protractor con seguridad porque será reemplazado completamente. Durante la instalación se descargaron algunos binarios ya que Cypress viene con una interfaz de usuario integrada en Electron como corredor de pruebas interactivo.

Usando la bandera --addCypressTestScripts se añadieron dos prácticos scripts npm para hacer más cómodo el trabajo con Cypress. Uno para ejecutar las pruebas e2e headless y el otro script que ejecuta las pruebas con el runner de Cypress UI:

 // package.json scripts "cy:run": "cypress run", "cy:open": "cypress open"

Si se ejecutara uno de estos scripts de forma autónoma, la prueba fallaría porque intenta dirigirse a http://localhost:4200 donde no se sirve nada por el momento. Para arreglar esto, necesitamos abrir una segunda terminal y servir nuestra aplicación Angular de antemano con npm start.

Por suerte el esquema ajustó el comando e2e para que esto lo haga por ti automáticamente el constructor CLI. Puedes servir la aplicación e iniciar la prueba e2e con el siguiente comando:

npm run e2e

Cypress detectará que lo lanzamos por primera vez. Verifica su instalación y añade algunos archivos de ejemplo iniciales. Después de que la UI se haya abierto, podemos ver un test que ya ha sido creado para nosotros.

La UI de Cypress después de cy:open

Al seleccionar el test se ejecutará. Inicialmente la prueba fallará porque en realidad no probamos algo correctamente. Vamos a arreglar esto ahora.

Falla la prueba que aún no está implementada

Escribiendo algunas pruebas

Como primerísimo paso, tal y como proponen las mejores prácticas de Cypress, establecemos nuestra baseUrl global, para no tener que duplicarla en cada ejecución de la prueba. Añade lo siguiente a la configuración cypress.json:

// cypress.json{ "baseUrl": "http://localhost:4200"}

Después, escribimos nuestro primer test de humo que sólo comprueba si el título de la aplicación por defecto está establecido en la página de inicio de Angular. Por lo tanto, cambiamos el contenido del spec.ts por el siguiente:

// spec.tsit('smoke test', () => { cy.visit('/'); cy.contains('cypress-e2e-testing-angular app is running!');});

La prueba comienza enrutando a nuestra baseUrl y procede a consultar cualquier elemento que contenga el texto cypress-e2e-testing-angular app is running!!!

Probando los flujos de usuarios

Esta prueba ya debería funcionar, pero vamos a escribir algunas más interactivas. Como los e2e son intrínsecamente más lentos que las pruebas unitarias, está totalmente bien tener pruebas e2e que modelen todo el flujo de usuario para una función.

Por ejemplo, queremos comprobar si algunas características de la página de inicio son válidas: Nuestra página debe contener el título y el texto ng generate en el terminal por defecto, pero cuando los usuarios hacen clic en el botón Material de Angular, queremos asegurarnos de que el comando ng add adecuado se muestra en la vista del terminal de abajo.

Puedes reemplazar el contenido de tu archivo de prueba con esto:

// spec.tsdescribe('When Angular starting page is loaded', () => { beforeEach(() => { cy.visit('/'); }); it('has app title, shows proper command by default and reacts on command changes', () => { cy.contains('cypress-e2e-testing-angular'); cy.contains('.terminal', 'ng generate component xyz'); cy.contains('Angular Material').click(); cy.contains('.terminal', 'ng add @angular/material'); });});

Refactorizamos nuestro conjunto de pruebas añadiendo un bloque describe para capturar todas las pruebas que se ejecutan cuando se carga la página de inicio. Como visitamos la baseUrl cada vez, trasladamos esto a la llamada beforeEach. Por último combinamos las pruebas básicas de humo con la prueba de la vista terminal en la página de inicio.

Es importante saber que no hay que almacenar los resultados de las consultas de Cypress en variables, sino que hay que trabajar con cierres. Además, seleccionamos elementos por clases CSS y contenido de texto, que pueden ser demasiado frágiles. Se recomienda utilizar atributos data- para seleccionar elementos.

Cypress tiene un montón de grandes características y posibilidades. No las cubriremos todas porque nuestro objetivo es centrarnos en el primer punto de partida. La documentación oficial es realmente buena y cubre todo sobre cómo interactuar con los elementos.

Si vuelves a ejecutar este conjunto de pruebas, deberías ver la UI haciendo clic a través de cada escenario y las tres pruebas deberían pasar esta vez. ✔✔✔

Ejecutando nuestra primera suite de pruebas de Cypress con éxito

Configurando la Integración Continua

Ahora que nuestras pruebas se ejecutan localmente, vamos a poner en marcha un pequeño pipeline de CI (integración continua). Una buena manera de preparar esto, es crear scripts npm y combinarlos para que el sistema de construcción pueda utilizar un solo script como punto de entrada. Siguiendo este método, puedes probar los pasos de CI localmente antes de ponerlos en línea. Además, los scripts npm son bastante independientes de cualquier sistema de construcción real.

En CI, tenemos que iniciar nuestro servidor en segundo plano y esperar a que empaquete nuestra aplicación, lo que puede tardar un tiempo. Luego tenemos que iniciar el corredor de pruebas de Cypress, pasar por las pruebas y apagar el servidor cuando las pruebas terminen. Por suerte podemos hacer todo esto con una sola utilidad llamada start-server-and-test como se describe en los docs de Cypress:

npm install --save-dev start-server-and-test

Una vez instalado esto, utilizamos el serve de Angular que actualmente está detrás de npm start y lo combinamos con el comando headless cy:run:

 // package.json scripts "start": "ng serve", "cy:run": "cypress run", "e2e:ci": "start-server-and-test start http://localhost:4200 cy:run"

Seguramente podrías usar una build de producción o construirla previamente y servir la app usando cualquier servidor http. En aras de la concisión, dejaré estas mejoras para ti.

Circle CI

Para nuestro ejemplo, elegimos CircleCI porque se integra muy bien con GitHub, es de uso común allí y tiene un plan gratuito. Puedes utilizar cualquier otro sistema de CI como Jenkins o GitLab (con el que tengo más experiencia). Después de iniciar sesión en CircleCI y conectar con nuestra cuenta de GitHub, puedes seleccionar el repositorio y crear un nuevo proyecto a través de su dashboard.

Para configurar el pipeline, podrías escribir un config.ymlseleccionando una plantilla y ajustándola a tus necesidades y eventualmente ejecutar el script e2e. Afortunadamente Cypress dispone de unas configuraciones listas para usar (llamadas Orbs) para CircleCI que ya incluyen la instalación de dependencias, caché y demás. Antes de poder usarlo, debemos visitar la Configuración de la Organización para habilitar los runners de terceros.

# circleci/config.ymlversion: 2.1orbs: # This Orb includes the following: # - checkout current repository # - npm install with caching # - start the server # - wait for the server to respond # - run Cypress tests # - store videos and screenshots as artifacts on CircleCI cypress: cypress-io/cypress@1workflows: build: jobs: - cypress/run: start: npm start wait-on: 'http://localhost:4200' store_artifacts: true

El pipeline sólo tiene un trabajo: Ejecutar todas las pruebas e2e. Comprueba la rama actual, instala todas las dependencias incluyendo la caché, inicia el servidor de aplicaciones y ejecuta nuestras pruebas. Además, se suben vídeos (grabados por defecto) y capturas de pantalla (en caso de que las pruebas fallen) como artefactos de CircleCI para su posterior inspección.*

CircleCI Dashboard

Conclusión

Los pasos de esta guía son bastante mínimos. Puedes usar tu proyecto Angular existente, puedes cambiar la configuración de tus suites de prueba Cypress y escribir un montón de pruebas más significativas. Además, puedes definir scripts npm para diferentes escenarios y entornos y, por supuesto, todo tu pipeline de construcción puede extenderse con linting, pruebas unitarias, construcción e incluso despliegue de tu aplicación. Sin embargo, esto debe ser un primer paso que muestra cómo las pruebas automatizadas de extremo a extremo se pueden configurar en la actualidad.

Espera hasta que escribas pruebas reales de Cypress para tu aplicación. Te divertirás.

Mind blown gif

Espero que también encuentres algún valor en este artículo. Si tienes alguna pregunta o comentario, házmelo saber. Sus comentarios son muy bienvenidos!

Puede encontrar las fuentes de esta guía en GitHub:

MrCube42 / cypress-e2e-testing-angular

Ejemplo de aplicación Angular 9 usando Cypress para pruebas de extremo a extremo.

CypressE2eTestingAngular

Este proyecto fue generado con la versión 9.0.6 de Angular CLI.

Servidor de desarrollo

Ejecuta ng serve para un servidor dev. Navegue hasta http://localhost:4200/. La aplicación se recargará automáticamente si cambias alguno de los archivos fuente.

Código de andamiaje

Ejecuta ng generate component component-name para generar un nuevo componente. También puede utilizar ng generate directive|pipe|service|class|guard|interface|enum|module.

Construir

Ejecutar ng build para construir el proyecto. Los artefactos de construcción se almacenarán en el directorio dist/. Utilice la bandera --prod para una construcción de producción.

Ejecutar pruebas unitarias

Run ng test para ejecutar las pruebas unitarias a través de Karma.

Ejecutar pruebas de extremo a extremo

Run npm run e2e para ejecutar las pruebas de extremo a extremo a través de Cypress.

Ayuda adicional

Para obtener más ayuda sobre el CLI de Angular utiliza ng help o ve a consultar el README del CLI de Angular.

Leave a Reply