Playwright: testing E2E que por fin funciona
Blog
4 de marzo de 20268 min

Playwright: testing E2E que por fin funciona

Cypress estuvo bien, pero Playwright cambió las reglas del juego. Te explico por qué lo uso en todos mis proyectos y cómo empezar desde cero.

testingplaywrighte2efrontend

Si llevas tiempo en el mundo del frontend, probablemente hayas escuchado hablar de Cypress. Y sí, Cypress fue un gran salto respecto a Selenium. Pero desde que llegó Playwright, no he vuelto atrás.

¿Qué es Playwright?

Playwright es un framework de testing E2E (end-to-end) desarrollado por Microsoft. Lo que lo hace diferente es que no está construido sobre WebDriver — tiene su propio protocolo de comunicación con los navegadores, lo que lo hace significativamente más rápido y estable.

Soporta Chromium, Firefox y WebKit (Safari) desde una misma API. Eso significa que con un solo test verificas que tu aplicación funciona en los tres motores de navegador más importantes del mundo.

Por qué cambié de Cypress a Playwright

Con Cypress estaba bien, pero tenía fricciones constantes:

  • Solo corría en Chromium de forma nativa
  • Los tests multi-tab eran un dolor de cabeza
  • La ejecución en CI era lenta
  • El manejo de iframes era complicado

Playwright resuelve todos esos puntos. Y lo hace con una API que, una vez que la aprendes, se siente natural.

Instalación

npm init playwright@latest

El wizard te pregunta si quieres TypeScript o JavaScript, dónde poner los tests y si quiere instalar los navegadores. En menos de dos minutos tienes todo listo.

La estructura que genera:

playwright.config.ts
tests/
  example.spec.ts
tests-examples/
  demo-todo-app.spec.ts

Tu primer test

import { test, expect } from '@playwright/test'
 
test('la página de inicio carga correctamente', async ({ page }) => {
  await page.goto('http://localhost:3000')
 
  await expect(page).toHaveTitle(/LHZ/)
  await expect(page.getByRole('heading', { name: /software/i })).toBeVisible()
})

Tres cosas que hay que notar aquí:

  1. page.goto espera automáticamente a que la página cargue
  2. expect tiene assertions específicos para el DOM — no necesitas cy.wait()
  3. El test es async/await puro — sin sintaxis especial que aprender

Locators: la clave de tests robustos

El mayor problema del testing E2E tradicional son los selectores frágiles. Los tests que seleccionan por clase CSS o ID se rompen con cualquier refactor.

Playwright promueve los locators semánticos:

// ❌ Frágil — se rompe si cambia el CSS
page.locator('.btn-primary')
 
// ✅ Robusto — selecciona por rol accesible
page.getByRole('button', { name: 'Enviar' })
 
// ✅ Robusto — selecciona por label del formulario
page.getByLabel('Email')
 
// ✅ Robusto — selecciona por texto visible
page.getByText('Contacto')
 
// ✅ Robusto — test ID explícito
page.getByTestId('submit-button')

Un efecto secundario positivo: si tus locators semánticos fallan, tu app probablemente tiene problemas de accesibilidad.

Ejecución en paralelo

Por defecto, Playwright corre los tests en paralelo entre archivos. Puedes configurar cuántos workers usar:

// playwright.config.ts
export default defineConfig({
  workers: process.env.CI ? 2 : '50%',
})

En CI usas 2 workers para no saturar la máquina. En local usas el 50% de los cores disponibles. Esto solo es posible porque Playwright tiene aislamiento real entre tests — cada test tiene su propio contexto de navegador.

UI Mode: el game changer para debugging

npx playwright test --ui

Esto abre una interfaz visual donde puedes:

  • Ver cada test con su timeline de acciones
  • Ver capturas de pantalla en cada paso
  • Re-ejecutar tests individualmente
  • Hacer time travel debugging — volver atrás en el tiempo del test

Es el Devtools del testing E2E. Una vez que lo usas, debuggear tests con console.log parece prehistórico.

Codegen: genera tests grabando tu navegación

npx playwright codegen http://localhost:3000

Playwright abre el navegador y graba cada acción que realizas, generando el código del test en tiempo real. No es perfecto para tests de producción, pero es una forma brutal de empezar un test complejo sin escribir desde cero.

Integración con CI (GitHub Actions)

name: Playwright Tests
on: [push, pull_request]
 
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
      - run: npm ci
      - run: npx playwright install --with-deps
      - run: npx playwright test
      - uses: actions/upload-artifact@v4
        if: failure()
        with:
          name: playwright-report
          path: playwright-report/

Lo más importante de este workflow: si un test falla, sube el reporte como artifact. Puedes descargarlo y ver exactamente qué falló, con capturas de pantalla y video incluidos.

Mi configuración recomendada para proyectos Next.js

// playwright.config.ts
import { defineConfig, devices } from '@playwright/test'
 
export default defineConfig({
  testDir: './tests',
  fullyParallel: true,
  retries: process.env.CI ? 2 : 0,
  workers: process.env.CI ? 2 : undefined,
  reporter: 'html',
 
  use: {
    baseURL: 'http://localhost:3000',
    trace: 'on-first-retry',
    screenshot: 'only-on-failure',
  },
 
  projects: [
    { name: 'chromium', use: { ...devices['Desktop Chrome'] } },
    { name: 'firefox',  use: { ...devices['Desktop Firefox'] } },
    { name: 'webkit',   use: { ...devices['Desktop Safari'] } },
    { name: 'mobile',   use: { ...devices['iPhone 14'] } },
  ],
 
  webServer: {
    command: 'npm run dev',
    url: 'http://localhost:3000',
    reuseExistingServer: !process.env.CI,
  },
})

El webServer levanta automáticamente Next.js antes de correr los tests. En CI siempre levanta uno nuevo; en local reutiliza el que ya tengas corriendo.

¿Cuándo usar Playwright vs tests unitarios?

Los tests E2E no reemplazan los tests unitarios — los complementan.

  • Tests unitarios: lógica pura, funciones, hooks, utils
  • Tests de integración: componentes con sus dependencias
  • Tests E2E (Playwright): flujos críticos del usuario de principio a fin

Mi regla: los flujos que, si se rompen, impactan directamente en dinero o en la experiencia del usuario van a Playwright. Login, checkout, formularios de contacto, navegación principal.

El resto — tests unitarios con Vitest o Jest.

Conclusión

Playwright es hoy la herramienta de testing E2E más completa del ecosistema JavaScript. Rápido, estable, con soporte multi-navegador real y una DX que hace que escribir tests sea, si no divertido, al menos tolerable.

Si estás empezando un proyecto nuevo, ponlo desde el primer día. Si tienes un proyecto existente, empieza por los flujos más críticos y ve añadiendo cobertura gradualmente.