Introducción
Las pruebas end-to-end tienen fama de ser lentas e inestables. Las herramientas basadas en Selenium corren en un proceso separado del navegador, lo que genera problemas de temporización y pruebas que fallan aleatoriamente incluso cuando la aplicación funciona correctamente. Cypress adopta un enfoque diferente: corre dentro del propio navegador, en el mismo event loop que la aplicación. Esto elimina toda una categoría de problemas de temporización y hace que las pruebas sean más rápidas de escribir y más fáciles de depurar.
¿Qué es Cypress?
Cypress es una herramienta de pruebas open-source construida para aplicaciones JavaScript modernas. Corre directamente en el navegador y funciona con React, Angular y Vue.js sin configuración adicional. Incluye un test runner gráfico que muestra exactamente lo que ocurrió en cada paso, además de un mecanismo de espera automática que elimina la necesidad de sleeps o waits explícitos en tus pruebas.
Características Principales de Cypress
- Time Travel: Cypress toma snapshots mientras corren las pruebas. Pasa el cursor sobre cualquier comando en el log para ver el estado de la aplicación en ese momento.
- Depurabilidad: mensajes de error legibles y stack traces claros. Los fallos describen lo que ocurrió, no solo qué aserción falló.
- Espera Automática: Cypress espera a los elementos del DOM, las solicitudes de red y las animaciones antes de continuar. No necesitas dispersar
cy.wait(1000)por tus pruebas. - Recargas en Tiempo Real: los archivos de prueba se recargan automáticamente al guardarlos.
- Control de Tráfico de Red: intercepta y reemplaza solicitudes HTTP para probar estados de error y casos límite sin depender de un backend activo.
¿Por qué Usar Cypress?
Las pruebas inestables son peores que ninguna prueba: erosionan la confianza hasta que el equipo empieza a ignorar los fallos. El modelo in-process de Cypress elimina la mayoría de las race conditions que causan inestabilidad en otras herramientas. La GUI interactiva hace que depurar fallos sea rápido, ya que puedes ver exactamente cómo estaba la aplicación en el momento exacto en que falló la prueba.
Cómo Implementar Cypress
Instalación
Asegúrate de tener Node.js instalado y, a continuación, añade Cypress a tu proyecto:
npm install cypress --save-dev
O bien, usando yarn:
yarn add cypress --dev
Configuración Inicial
Abre Cypress por primera vez para generar las carpetas y archivos necesarios:
npx cypress open
Esto crea una carpeta cypress con:
fixtures/para datos de prueba estáticos.integration/para archivos de prueba (specs).plugins/para extender o modificar el comportamiento de Cypress.support/para comandos personalizados reutilizables y configuración global.
Configuración
Personaliza los ajustes en cypress.json:
{
"baseUrl": "http://localhost:3000",
"viewportWidth": 1280,
"viewportHeight": 720,
"video": true
}
baseUrl es la URL donde corre tu aplicación. viewportWidth y viewportHeight definen las dimensiones del navegador. video habilita la grabación de las ejecuciones de prueba.
Creando un Sistema de Ejemplo
Configurando una Aplicación de Ejemplo
Crea una aplicación Todo básica usando React:
Paso 1: Crear una Nueva App React
npx create-react-app cypress-todo-app
cd cypress-todo-app
Paso 2: Construir la Aplicación Todo
Implementa una interfaz sencilla donde los usuarios puedan agregar y eliminar elementos de tareas, luego inicia el servidor de desarrollo:
npm start
Escribiendo Pruebas con Cypress
Paso 1: Crear un Nuevo Archivo de Prueba
Dentro de cypress/integration/, crea todo.spec.js.
Paso 2: Escribir las Pruebas
describe('Todo App', () => {
beforeEach(() => {
cy.visit('/');
});
it('Displays the app title', () => {
cy.contains('h1', 'Todo App');
});
it('Can add a new todo item', () => {
const newItem = 'Buy milk';
cy.get('input[name="new-todo"]').type(`${newItem}{enter}`);
cy.get('.todo-list').should('contain', newItem);
});
it('Can remove a todo item', () => {
const itemToRemove = 'Buy milk';
cy.get('.todo-list')
.contains(itemToRemove)
.parent()
.find('.delete-button')
.click();
cy.get('.todo-list').should('not.contain', itemToRemove);
});
});
Paso 3: Ejecutar las Pruebas
npx cypress open
Selecciona todo.spec.js para ejecutar las pruebas de forma interactiva.
Ejecutando Pruebas y Analizando los Resultados
El test runner de Cypress muestra cada comando a medida que se ejecuta. Puedes pasar el cursor sobre cualquier comando en el log para ver un snapshot de la aplicación en ese punto. Las pruebas fallidas generan capturas de pantalla automáticamente, y la grabación en video captura la ejecución completa.
Funcionalidades Avanzadas
Fixtures
Las fixtures cargan datos estáticos desde archivos hacia tus pruebas:
cy.fixture('user.json').then((user) => {
// Use user data in your tests
});
Comandos Personalizados
El código de configuración repetido debe ir en comandos personalizados, no copiado entre specs.
En cypress/support/commands.js:
Cypress.Commands.add('login', (email, password) => {
cy.visit('/login');
cy.get('input[name="email"]').type(email);
cy.get('input[name="password"]').type(password);
cy.get('form').submit();
});
Usa el comando personalizado en tus pruebas:
cy.login('test@example.com', 'password123');
Integración Continua con Cypress
Ejemplo con GitHub Actions
Crea un archivo .github/workflows/cypress.yml:
name: Cypress Tests
on: [push]
jobs:
cypress-run:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install Dependencies
run: npm install
- name: Run Cypress Tests
run: npx cypress run
Esto ejecuta Cypress en modo headless en cada push.
Conclusión
Vale la pena adoptar Cypress si tu equipo ha sufrido con pruebas Selenium inestables o con el ciclo de retroalimentación lento de las herramientas tradicionales de E2E. La arquitectura in-browser resuelve el problema de temporización desde la raíz. La GUI interactiva hace que depurar sea práctico en lugar de doloroso. Empieza con un puñado de pruebas que cubran los flujos de usuario más utilizados, consigue que pasen de forma confiable en CI y expande desde ahí.