
Automatizando la Web Moderna: Cypress y Playwright para pruebas End-to-End
Tabla de contenido
Acceso Rápido

El desarrollo web moderno —SPAs, micro-frontends, apps progresivas— exige pruebas que garanticen que toda la experiencia del usuario funcione sin problemas, desde el login hasta la interacción más compleja con la UI.
Las pruebas end-to-end (E2E) verifican que el frontend, backend, APIs y la red funcionen de manera integrada. Entre los frameworks más populares para E2E se encuentran Cypress y Playwright, que ofrecen diferentes filosofías, ventajas y flujos de trabajo.
¿Qué es el testing E2E y por qué es importante?
El End-to-End testing (o pruebas de extremo a extremo) es una metodología de QA que verifica un flujo completo de usuario, reproduciendo la experiencia real en un entorno lo más parecido posible a producción.
En lugar de probar funciones aisladas (como en unit tests) o módulos específicos (como en integration tests), las pruebas E2E:
- Abren la aplicación como lo haría un usuario real.
- Interactúan con botones, formularios, navegación, APIs, cookies, localStorage, sesiones, etc.
- Comprueban que todo el sistema responde correctamente.
- Las pruebas E2E verifican flujos completos de usuario:
- Login → Dashboard → Interacción → Logout
- Interacciones con APIs y servicios externos
- Manejo de estados persistentes y asincronía
A diferencia de pruebas unitarias o de integración, las E2E validan la integración completa del sistema, asegurando que los cambios en el código no rompan la experiencia del usuario final. Las pruebas unitarias e integrales no garantizan que la aplicación funcione en su conjunto.
El E2E asegura:
- Que la UI responde
- Que el backend funciona
- Que el sistema completo está integrado
- Que no hay regresiones funcionales
Cypress vs Playwright
Cypress como Playwright son frameworks líderes para testing E2E, pero tienen filosofías distintas. La elección depende del tipo de proyecto, arquitectura, equipo y necesidades de CI/CD.
Cypress
- Corre dentro del navegador, inyectado en la propia ventana de la aplicación.
- Excelente para observar la ejecución paso a paso.
- Limita algunos escenarios que requieran múltiples pestañas o ventanas.
- No soporta todos los eventos del navegador porque no tiene control completo del motor.
- Debugging muy intuitivo (time-travel, UI interactiva).
Playwright
- Controla el navegador desde fuera, a través de su API.
- Soporta múltiples páginas, contextos y usuarios paralelos.
- Permite automatizar navegadores reales sin restricciones.
- Más poder, más flexibilidad y más funcionalidades a nivel de navegador.
Ejemplos prácticos
Login Flow con Cypress (cypress/e2e/login.cy.js)
describe('Flujo de login', () => {
it('inicia sesión correctamente y muestra el dashboard', () => {
cy.visit('https://mi-app.com/login')
cy.get('input[name="email"]').type('usuario@ejemplo.com')
cy.get('input[name="password"]').type('miPassword{enter}')
cy.url().should('include', '/dashboard')
cy.contains('Bienvenido, Usuario')
cy.get('button[aria-label="Cerrar sesión"]').click()
cy.url().should('include', '/login')
})
})
Nota: Cypress maneja esperas automáticas, reduciendo tests frágiles
Login Flow con Playwright (tests/login.spec.js)
import { test, expect } from '@playwright/test';
test('flujo de login exitoso', async ({ page }) => {
await page.goto('https://mi-app.com/login');
await page.fill('input[name="email"]', 'usuario@ejemplo.com');
await page.fill('input[name="password"]', 'miPassword');
await page.click('button[type="submit"]');
await expect(page).toHaveURL(/.*\/dashboard/);
await expect(page.locator('h1')).toContainText('Bienvenido, Usuario');
await page.click('button[aria-label="Cerrar sesión"]');
await expect(page).toHaveURL(/.*\/login/);
});Configuración avanzada en Playwright (playwright.config.ts)
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
testDir: './tests',
timeout: 30_000,
fullyParallel: true,
retries: 1,
use: {
baseURL: 'https://mi-app.com',
headless: true,
screenshot: 'only-on-failure',
video: 'retain-on-failure',
trace: 'retain-on-failure',
viewport: { width: 1280, height: 720 },
},
});Mocking de APIs
cy.intercept('POST', '/api/login', { statusCode: 200, body: { token: '12345' } }).as('loginRequest');
cy.get('button[type="submit"]').click();
cy.wait('@loginRequest');await page.route('**/api/login', route =>
route.fulfill({ status: 200, body: JSON.stringify({ token: '12345' }) })
);
await page.click('button[type="submit"]');Testing de accesibilidad (a11y)
import { injectAxe, checkA11y } from '@axe-core/playwright';
await page.goto('/');
await injectAxe(page);
await checkA11y(page);Medición y Mitigación del Flakiness
await page.locator('button#submit').waitFor({ state: 'visible' });
await page.locator('button#submit').click();Buenas Prácticas
- Usa un Testing Pyramid: Unit > Integration > E2E.
- Prioriza los flujos de negocio más importantes para el usuario.
- Mantén tests pequeños, legibles y aislados.
- Evitar waits fijos.
- Mantener tests independientes.
Elección entre Cypress y Playwright
Usar Cypress cuando los tests no requieren multi-tab ni Safari/iOS reales.
Usar Playwright cuando se necesita soporte completo de navegadores y paralelización real.
Te recomendamos en video
Blogs relacionados

IA Local en VS Code con Ollama y Phi-3

Integración de Algoritmos de Machine Learning en una Arquitectura de Microservicios

Netflix y su arquitectura de microservicios: Lecciones de escalabilidad para tu empresa

Arquitectura de microservicios: Diseño de sistemas escalables

Nuestros eventos en 2025: un año de crecimiento y networking
