E2E - Ejemplos Prácticos Avanzados
⚙️ Objetivo
Estos ejemplos avanzados de E2E - End to End Testing profundizan en casos reales de automatización compleja, simulaciones, paralelización, autenticación persistente, manejo de datos dinámicos, interceptores de red, y validación de estados internos.
Se utilizan principalmente Playwright y Cypress como base, con técnicas aplicables también a Selenium o WebdriverIO.
🧩 1. Autenticación Persistente y Reutilización de Sesión (Playwright)
Guardar la sesión de un usuario autenticado para evitar logins repetitivos y acelerar la suite E2E.
// tests/auth.setup.ts
import { test as setup, expect } from '@playwright/test'
import fs from 'fs'
const STORAGE_STATE = 'playwright/.auth/user.json'
setup('guardar sesión autenticada', async ({ page }) => {
await page.goto('https://miapp.test/login')
await page.fill('#email', 'usuario@example.com')
await page.fill('#password', '123456')
await page.click('button[type="submit"]')
await expect(page).toHaveURL(/dashboard/)
await page.context().storageState({ path: STORAGE_STATE })
})
`
// playwright.config.ts
use: {
storageState: 'playwright/.auth/user.json'
}
Ahora todas las pruebas posteriores reutilizan la sesión, evitando autenticarse en cada ejecución.
🧩 2. Interceptar y Modificar Respuestas de API (Playwright)
Simular respuestas dinámicas del backend sin alterar el servidor.
import { test, expect } from '@playwright/test'
test('interceptar respuesta del servidor', async ({ page }) => {
await page.route('**/api/productos', route => {
const mockResponse = {
status: 200,
contentType: 'application/json',
body: JSON.stringify([
{ id: 1, nombre: 'Producto Falso A', precio: 10 },
{ id: 2, nombre: 'Producto Falso B', precio: 20 }
])
}
route.fulfill(mockResponse)
})
await page.goto('https://miapp.test/tienda')
const productos = await page.locator('.producto').allTextContents()
expect(productos).toContain('Producto Falso A')
})
Ideal para aislar pruebas de la infraestructura backend o validar comportamiento ante respuestas personalizadas.
🧩 3. Validar Estados Internos del Frontend (Cypress + Redux / Zustand)
Ejemplo de cómo verificar que el estado global del frontend cambie correctamente tras una acción del usuario.
describe('Gestión de estado global (Redux)', () => {
it('Verifica que el carrito se actualiza en el store', () => {
cy.visit('/tienda')
cy.window().its('store').invoke('getState').then(initial => {
expect(initial.carrito.items).to.have.length(0)
})
cy.get('.producto:first-child button.agregar-carrito').click()
cy.window().its('store').invoke('getState').then(final => {
expect(final.carrito.items).to.have.length(1)
})
})
})
Permite probar la lógica interna de la aplicación sin depender únicamente del DOM.
🧩 4. Pruebas Condicionales y Entornos Variables (Playwright)
Ejecutar flujos diferentes según el entorno o rol del usuario.
import { test, expect } from '@playwright/test'
test('acceso según rol de usuario', async ({ page }) => {
const role = process.env.USER_ROLE || 'user'
await page.goto('https://miapp.test/dashboard')
if (role === 'admin') {
await expect(page.locator('text=Panel de Administración')).toBeVisible()
} else {
await expect(page.locator('text=Acceso Denegado')).toBeVisible()
}
})
Permite validar permisos y comportamientos adaptados a distintos contextos de despliegue (QA, staging, producción).
🧩 5. Pruebas Multitab y Comunicación Entre Pestañas (Playwright)
Simular interacciones entre pestañas, útil en flujos como notificaciones o webs colaborativas.
test('sincronización entre pestañas', async ({ browser }) => {
const contexto = await browser.newContext()
const tab1 = await contexto.newPage()
const tab2 = await contexto.newPage()
await tab1.goto('https://miapp.test/documento')
await tab2.goto('https://miapp.test/documento')
await tab1.fill('#titulo', 'Documento E2E')
await tab1.keyboard.press('Control+S')
await tab2.reload()
const titulo = await tab2.inputValue('#titulo')
expect(titulo).toBe('Documento E2E')
})
Demuestra control avanzado del entorno multi-pestaña y sincronización de estados.
🧩 6. Validación Visual (Visual Regression Testing)
Comparar capturas de pantalla actuales con imágenes base para detectar cambios visuales no deseados.
import { test, expect } from '@playwright/test'
test('comparación visual del dashboard', async ({ page }) => {
await page.goto('https://miapp.test/dashboard')
await expect(page).toHaveScreenshot('dashboard-base.png', {
fullPage: true,
maxDiffPixels: 100
})
})
Detecta regresiones visuales provocadas por cambios de CSS, layout o componentes UI.
🧩 7. Datos Dinámicos y Factories (Playwright + Faker)
Generar datos aleatorios pero coherentes para evitar dependencias de datos fijos.
import { test, expect } from '@playwright/test'
import { faker } from '@faker-js/faker'
test('crear usuario dinámico', async ({ page }) => {
const usuario = {
nombre: faker.person.fullName(),
email: faker.internet.email(),
password: faker.internet.password(8)
}
await page.goto('https://miapp.test/registro')
await page.fill('#nombre', usuario.nombre)
await page.fill('#email', usuario.email)
await page.fill('#password', usuario.password)
await page.click('button[type="submit"]')
await expect(page.locator('.mensaje-exito')).toHaveText(/cuenta creada/i)
})
Los factories permiten tests más realistas y resistentes a cambios de datos.
🧩 8. Control de Red, Tiempos y Retrasos (Cypress)
Simular respuestas lentas o errores de red para probar la resiliencia del frontend.
describe('Simulación de red lenta y error 500', () => {
it('Muestra mensaje de error cuando el servidor falla', () => {
cy.intercept('GET', '/api/usuarios', {
statusCode: 500,
delay: 2000,
body: { error: 'Error interno del servidor' }
}).as('usuariosFallan')
cy.visit('/usuarios')
cy.wait('@usuariosFallan')
cy.contains('No se pudieron cargar los usuarios').should('be.visible')
})
})
Útil para validar comportamiento bajo condiciones reales de latencia o caída del backend.
🧩 9. Tests Paralelos y Data-driven (Playwright)
Ejecutar el mismo flujo con múltiples conjuntos de datos.
import { test, expect } from '@playwright/test'
const casos = [
{ nombre: 'Eduardo', email: 'eduardo@example.com' },
{ nombre: 'Lucía', email: 'lucia@example.com' },
{ nombre: 'Mario', email: 'mario@example.com' }
]
for (const caso of casos) {
test(`formulario con ${caso.nombre}`, async ({ page }) => {
await page.goto('https://miapp.test/contacto')
await page.fill('#nombre', caso.nombre)
await page.fill('#email', caso.email)
await page.fill('#mensaje', 'Prueba de mensaje')
await page.click('button[type="submit"]')
await expect(page.locator('.mensaje-exito')).toBeVisible()
})
}
Cada caso se ejecuta como prueba independiente, lo que facilita cobertura de múltiples combinaciones de entrada.
🧩 10. Integración con CI/CD y Artifacts Avanzados (Playwright)
Ejemplo de pipeline con reportes HTML, vídeos, trazas y reintentos automáticos.
name: Advanced E2E Suite
on: [push, pull_request]
jobs:
playwright-tests:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
browser: [chromium, firefox, webkit]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- name: Instalar dependencias
run: npm ci
- name: Ejecutar tests
run: npx playwright test --browser=${{ matrix.browser }} --reporter=html
- name: Subir artefactos
uses: actions/upload-artifact@v4
with:
name: playwright-report-${{ matrix.browser }}
path: playwright-report/
Este flujo genera reportes detallados por navegador y permite análisis visual tras cada ejecución CI.
🧠 Conclusiones Prácticas
- La potencia del E2E radica en reproducir condiciones reales: usuarios, red, roles y datos dinámicos.
- Los tests avanzados deben ser modulares, configurables y paralelizables.
- Los mocks, interceptores y factories reducen la fragilidad y aumentan la velocidad.
- La reutilización de sesión y entorno mejora la eficiencia de ejecución.
- La observabilidad (logs, vídeos, trazas) facilita el diagnóstico y mantenimiento.
- Una buena estrategia incluye tanto validaciones visuales como de estado lógico.
Estos patrones y ejemplos permiten diseñar suites E2E robustas, adaptables y preparadas para integrarse en pipelines empresariales con calidad de producción.
¿Te gusta este contenido? Suscríbete vía RSS