Curso Completo de Cypress: Automatización E2E Profesional

Índice General

  1. Introducción y Características Principales
  2. Instalación y Configuración del Entorno
  3. Estructura Básica de una Prueba
  4. Interacción con Elementos y Selectores
  5. Control de Tiempo y Gestión de Ventanas
  6. Pruebas Basadas en Datos (Fixtures)
  7. Pruebas de APIs (HTTP Requests)
  8. Buenas Prácticas y Configuración Avanzada
  9. Pruebas de Accesibilidad Web (A11y)
  10. Validación de Alertas y Flujos Dinámicos
  11. Dockerización de Pruebas en Cypress

1. Introducción y Características Principales

Cypress es un framework de automatización de pruebas de última generación diseñado específicamente para la web moderna[cite: 2]. A diferencia de otras herramientas, Cypress se ejecuta directamente dentro del mismo ciclo de bucle de eventos que la aplicación (capa de interfaz de usuario)[cite: 2], lo que proporciona ejecuciones nativas extremadamente veloces y reduce la inestabilidad en los resultados.

Ventajas Técnicas

2. Instalación y Configuración del Entorno

Para inicializar un proyecto con Cypress, sigue la secuencia de comandos en tu terminal de desarrollo[cite: 5]:

# 1. Asegúrate de contar con Node.js instalado globalmente [cite: 6]
node -v

# 2. Inicializa el gestor de paquetes de Node dentro del directorio de tu proyecto [cite: 7]
npm init -y

# 3. Instala Cypress como una dependencia de desarrollo [cite: 8]
npm install cypress --save-dev

# 4. Abre la interfaz gráfica interactiva de Cypress por primera vez [cite: 9]
npm run cypress:open

Resolución del Error de Script Ausente (Missing Script)

Si al ejecutar el comando de apertura del entorno del test runner el sistema arroja el siguiente error[cite: 11, 12]:

npm error Missing script: "cypress:open"

Solución: Abre el archivo estructural package.json de la raíz y edita el objeto de comandos incluyendo el alias correspondiente[cite: 17]:

"scripts": {
  "test": "echo \"Error: no test specified\" && exit 1",
  "cypress:open": "cypress open"
}

3. Estructura Básica de una Prueba

Los archivos de pruebas de Cypress utilizan la extensión estándar *.cy.js [cite: 10] y deben ser ubicados bajo el directorio de trabajo cypress/e2e/[cite: 25]. Su estructura hereda la sintaxis de las librerías Mocha y Chai mediante las palabras reservadas describe (para definir suites) e it (para pruebas individuales)[cite: 26, 42].

Ejemplo Base: Validación de Apertura

describe('Suite: Pruebas de Apertura Web', () => {
  it('Debería navegar correctamente a la página de inicio y validar su título', () => {
    // Visita la URL especificada [cite: 27, 32]
    cy.visit('https://www.google.com/');
    
    // Asertar que el título sea coincidente de forma exacta [cite: 28, 33]
    cy.title().should('eq', 'Google');
  });
});

Tip: Puedes definir una propiedad baseUrl global en el archivo cypress.config.js para simplificar el uso de cy.visit() en tus archivos[cite: 23].

4. Interacción con Elementos y Selectores

Cypress proporciona el comando universal cy.get() para capturar nodos del árbol de documentos (DOM)[cite: 47]. Como estándar profesional, se aconseja priorizar los atributos exclusivos de pruebas (como IDs o selectores personalizados) antes que clases de diseño que cambien con regularidad[cite: 45].

Comandos de Acción Comunes

Ejemplo de Automatización Completa (Flujo Wikipedia)

describe('Suite: Interacción con el Buscador', () => {
  it('Debería realizar una búsqueda interactiva en Wikipedia', () => {
    cy.visit('https://es.wikipedia.org/wiki/Wikipedia:Portada'); [cite: 51]
    
    // Validar que la URL incluye el término esperado [cite: 44, 52]
    cy.url().should('include', 'wikipedia');
    
    // Interactuar con los elementos del DOM [cite: 53, 54, 55]
    cy.get('#p-search > .cdx-button--fake-button > .vector-icon').click();
    cy.get('#searchform > .cdx-search-input > [name="search"]').type('cypress');
    cy.get('#searchform > .cdx-search-input > .cdx-button').click();
    
    // Alternativa semántica para buscar botones por su texto visible [cite: 58, 59]
    // cy.contains('button', 'Buscar').click();

    // Aserción de existencia del bloque de contenido [cite: 61]
    cy.get('.mw-html-heading:contains("Portales")').should('exist');
  });
});

5. Control de Tiempo y Gestión de Ventanas

A pesar de que Cypress maneja colas de espera inteligentes automáticas, en ocasiones se requieren instrucciones explícitas de sincronización o de control de ventanas del navegador:

Función / Comando Descripción Técnica Ejemplo Práctico
cy.wait() Detiene la ejecución del flujo por un tiempo fijo en milisegundos[cite: 63]. (Usar con moderación) cy.wait(1000); // Espera 1 segundo [cite: 64]
cy.reload() Fuerza la recarga de la página actual en pantalla limpiando estados locales[cite: 65, 66]. cy.reload();
cy.exec() Ejecuta un comando nativo a nivel del sistema operativo anfitrión[cite: 67]. cy.exec('echo "Test running"');
{ force: true } Fuerza una acción o navegación ignorando si el elemento está oculto o bloqueado[cite: 99]. cy.visit('https://url-edicion', { force: true }); [cite: 99]

Control del Objeto Window

Si se requiere interactuar con el contexto global o forzar la redirección de enlaces diseñados para abrirse en pestañas nuevas, se puede capturar el objeto de la ventana gráfica directamente[cite: 101]:

cy.window().then((win) => {
  win.open('https://es.wikipedia.org/w/index.php?title=Wikipedia:Portada&action=edit'); [cite: 102]
});

6. Pruebas Basadas en Datos (Fixtures)

Los Fixtures son archivos JSON estáticos que contienen sets de datos estructurados independientes del código de pruebas[cite: 71]. Se gestionan dentro del directorio por defecto cypress/fixtures/[cite: 73].

1. Archivo de Datos (cypress/fixtures/usuarios.json) [cite: 73]

[
  {
    "nombre": "admin@gmail.com",
    "password": "juan123"
  },
  {
    "nombre": "user@gmail.com",
    "password": "user123"
  }
]

2. Consumo en la Suite de Pruebas [cite: 86]

describe('Suite: Autenticación con Datos Externos', () => {
  beforeEach(() => {
    cy.visit("https://es.wikipedia.org/wiki/Especial:Entrar"); [cite: 88]
  });

  it('Debería cargar y rellenar las credenciales del primer registro', () => {
    // Carga el fixture y resuelve la promesa de datos [cite: 91]
    cy.fixture('usuarios.json').then((datos) => {
      const usuario = datos[0]; [cite: 92]
      cy.get('#wpName1').type(usuario.nombre); [cite: 93]
      cy.get('#wpPassword1').type(usuario.password);
    });
  });
});

7. Pruebas de APIs (HTTP Requests)

Cypress no se limita a la interfaz gráfica; también puede actuar como cliente HTTP mediante el comando cy.request() para realizar llamadas directas a extremos (Endpoints) de API REST[cite: 109, 111, 114].

Ejemplo Avanzado: Consultas GET y Altas POST

describe('Suite: Pruebas de Integración de API', () => {

  it('Debería validar un método GET correctamente', () => {
    cy.request('GET', "https://reqres.in/api/users?page=2").then((response) => {
      // Validar código de estado HTTP exitoso [cite: 115]
      expect(response.status).to.eq(200);
      
      // Comprobar la existencia estructural y el tipo de dato de las propiedades [cite: 119, 120, 121]
      expect(response.body).to.have.property('data');
      expect(response.body.data).to.be.an('array');
      
      // Validar datos específicos internos [cite: 142, 143]
      expect(response.body.data[0]).to.have.property('id', 7);
    });
  });

  it('Debería dar de alta un recurso mediante un método POST', () => {
    const newUser = { "name": "Martín", "job": "QA Automation Lead" }; [cite: 128]
    
    cy.request('POST', "https://reqres.in/api/users", newUser).then((response) => {
      expect(response.status).to.eq(201); // 201 Created [cite: 133]
      expect(response.body).to.have.property('name', newUser.name); [cite: 134]
      expect(response.body).to.have.property('job', newUser.job); [cite: 135]
    });
  });
});

8. Buenas Prácticas y Configuración Avanzada

Organización Modular de Suites

Separa lógicamente tus archivos de prueba basándote en dominios o módulos funcionales del negocio[cite: 145, 146]:

describe('Módulo: Autenticación de Usuarios', () => { ... }); [cite: 147]
describe('Módulo: Gestión del Perfil de Usuario', () => { ... }); [cite: 149]
describe('Módulo: Procesos de Pago y Pasarela', () => { ... }); [cite: 151]

Uso de Alias (Alias con .as())

Asigna identificadores dinámicos amigables a tus consultas para reutilizarlas a lo largo del test sin duplicar localizadores[cite: 153]:

cy.get('img[alt="Logo corporativo"]').as('imagenPrincipal'); [cite: 154]
// Más adelante en tu código:
cy.get('@imagenPrincipal').should('be.visible'); [cite: 69]

Configuración Global de Medios (cypress.config.js)

Para activar y parametrizar la generación de evidencias en video o capturas automatizadas ante fallas en los pipelines, utiliza los siguientes indicadores[cite: 156]:

const { defineConfig } = require("cypress");

module.exports = defineConfig({
  video: true,                  // Graba un video de la ejecución del test [cite: 158]
  videoCompression: false,       // Evita ralentizaciones de compresión [cite: 159]
  screenshotOnRunFailure: true,  // Toma fotos automáticamente si un test falla [cite: 160]
  e2e: {
    setupNodeEvents(on, config) {
      // Eventos del ciclo de vida de Node aquí [cite: 162]
    },
  },
});

9. Pruebas de Accesibilidad Web (A11y)

Garantizar que tu portal cumpla con los estándares de accesibilidad internacional es sumamente sencillo acoplando el motor de auditoría axe-core al ecosistema de Cypress[cite: 165].

# Instalación del conector de accesibilidad en el proyecto [cite: 165]
npm install --save-dev cypress-axe

Implementación Completa

import 'cypress-axe'; // Inyección de los comandos de validación accesibles [cite: 167]

describe('Suite: Auditoría de Accesibilidad', () => {
  it('La página de inicio no debería poseer infracciones críticas de maquetación', () => {
    cy.visit('https://blazedemo.com'); [cite: 170]
    
    // Inyecta de forma interna el motor axe runtime [cite: 171]
    cy.injectAxe(); [cite: 171]
    
    // Ejecuta el análisis acotándolo a impactos críticos y serios [cite: 172, 173]
    cy.checkA11y(null, {
      includedImpacts: ['critical', 'serious'] [cite: 173]
    });
  });
});

10. Validación de Alertas y Flujos Dinámicos

Escucha de Alertas Nativas de la Ventana (window:alert)

Cypress atrapa y aprueba automáticamente los pop-ups informativos del navegador, pero permite interceptar el texto para auditar su contenido[cite: 183, 184]:

cy.on('window:alert', (textoAlerta) => { [cite: 184]
  expect(textoAlerta).to.equal('Product added'); // Valida el string de la alerta [cite: 185]
});

Comparación de Diferencia de Valores Dinámicos

Para comprobar que un descuento promocional alteró de manera real el balance final de una compra, se puede asertar el cambio de valor numérico[cite: 177]:

// Almacenar el estado original del elemento de precio [cite: 178]
const precioAntes = cy.get('.OrderSummary__price');

cy.get('[name="promo"]').type('CUPON_DESCUENTO'); [cite: 179]
cy.get('.btn-aplicar').click(); [cite: 180]

// El nuevo estado no debería ser idéntico al patrón anterior [cite: 181, 182]
const precioDespues = cy.get('.OrderSummary__price');
precioAntes.should('not.equal', precioDespues); [cite: 182]

11. Dockerización de Pruebas en Cypress

Para empaquetar de forma portable y limpia tus suites E2E impidiendo que dependan de las librerías gráficas locales de un sistema anfitrión, utiliza contenedores Docker.

1. Dockerfile (Ubicado en la raíz del proyecto) [cite: 189]

# Usar la imagen oficial preconfigurada con todas las dependencias y navegadores necesarios
FROM cypress/included:latest

# Directorio de trabajo interno del contenedor [cite: 190]
WORKDIR /e2e

# Copiar el directorio del proyecto local al espacio interno del contenedor [cite: 191]
COPY cypress/ ./
COPY cypress.config.js ./

# Comando de ejecución automatizado por defecto al instanciar el contenedor [cite: 192]
CMD ["cypress", "run"]

2. Comandos Operativos de la CLI