Que Es Playwright?
Playwright es un framework moderno de automatizacion de navegadores creado por Microsoft. Proporciona una API unica para controlar navegadores Chromium, Firefox y WebKit. Lanzado en 2020, se ha convertido rapidamente en la opcion mas popular para nuevos proyectos de automatizacion.
Por Que Playwright?
| Caracteristica | Playwright | Selenium |
|---|---|---|
| Auto-waiting | Incorporado | Waits manuales requeridos |
| Multi-navegador | Chromium, Firefox, WebKit | Requiere drivers separados |
| Velocidad | Muy rapido | Moderado |
| Locators | Basados en rol, texto, test-id | CSS, XPath, ID |
| Debugging | Trace Viewer, Inspector | Solo screenshots |
| API testing | Incorporado | Requiere herramienta separada |
| Codegen | Incorporado | No disponible |
| Ejecucion paralela | Nativa | Requiere Grid |
Configuracion de Playwright
JavaScript/TypeScript
npm init playwright@latest
Python
pip install playwright
playwright install
Escribiendo tu Primer Test
import { test, expect } from '@playwright/test';
test('usuario puede hacer login y ver dashboard', async ({ page }) => {
await page.goto('https://app.example.com/login');
await page.fill('[data-testid="email"]', 'admin@test.com');
await page.fill('[data-testid="password"]', 'secret123');
await page.click('[data-testid="submit"]');
await expect(page).toHaveURL('/dashboard');
await expect(page.locator('.welcome')).toHaveText('Welcome, Admin');
});
test('login invalido muestra error', async ({ page }) => {
await page.goto('https://app.example.com/login');
await page.fill('[data-testid="email"]', 'wrong@test.com');
await page.fill('[data-testid="password"]', 'wrongpass');
await page.click('[data-testid="submit"]');
await expect(page.locator('.error')).toHaveText('Credenciales invalidas');
});
Locators Poderosos
Locators Basados en Rol (Recomendado)
await page.getByRole('button', { name: 'Iniciar Sesion' }).click();
await page.getByRole('textbox', { name: 'Email' }).fill('admin@test.com');
await page.getByLabel('Email').fill('admin@test.com');
await page.getByPlaceholder('Ingresa tu email').fill('admin@test.com');
await page.getByText('Iniciar Sesion').click();
await page.getByTestId('login-submit').click();
Encadenamiento y Filtrado de Locators
await page.locator('.product-card').filter({ hasText: 'Mouse Inalambrico' })
.getByRole('button', { name: 'Agregar al Carrito' }).click();
await page.locator('.product-card').nth(0).click();
await page.locator('.product-card').first().click();
Auto-Waiting
// Sin waits manuales — Playwright lo maneja
await page.click('#submit');
// Playwright espera: visible, estable, habilitado, recibiendo eventos
await expect(page.locator('.result')).toHaveText('Exito');
// Playwright reintenta hasta que la asercion pasa (dentro del timeout)
Assertions Web-First
await expect(page).toHaveTitle('Dashboard');
await expect(page).toHaveURL(/dashboard/);
await expect(page.locator('.status')).toHaveText('Activo');
await expect(page.locator('.item')).toHaveCount(5);
await expect(page.locator('#btn')).toBeVisible();
await expect(page.locator('#btn')).toBeEnabled();
Configuracion
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
testDir: './tests',
timeout: 30000,
retries: process.env.CI ? 2 : 0,
workers: process.env.CI ? 4 : undefined,
reporter: [['html'], ['junit', { outputFile: 'results.xml' }]],
use: {
baseURL: 'https://app.example.com',
screenshot: 'only-on-failure',
video: 'retain-on-failure',
trace: 'retain-on-failure',
},
projects: [
{ name: 'chromium', use: { ...devices['Desktop Chrome'] } },
{ name: 'firefox', use: { ...devices['Desktop Firefox'] } },
{ name: 'webkit', use: { ...devices['Desktop Safari'] } },
{ name: 'mobile-chrome', use: { ...devices['Pixel 5'] } },
{ name: 'mobile-safari', use: { ...devices['iPhone 13'] } },
],
});
Funcionalidades Avanzadas
Trace Viewer
npx playwright test
npx playwright show-trace trace.zip
El trace muestra: screenshots en cada paso, snapshots del DOM, requests de red, logs de consola y codigo fuente.
Codegen — Grabar Tests
npx playwright codegen https://app.example.com
Codegen abre un navegador y graba tus interacciones, generando codigo de test en tiempo real.
API Testing (Incorporado)
test('crear usuario via API', async ({ request }) => {
const response = await request.post('/api/users', {
data: { name: 'Test User', email: 'test@example.com' },
});
expect(response.ok()).toBeTruthy();
const user = await response.json();
expect(user.name).toBe('Test User');
});
test('admin crea usuario via API, verifica en UI', async ({ page, request }) => {
const response = await request.post('/api/users', {
data: { name: 'Nuevo Usuario', email: 'new@test.com' }
});
const user = await response.json();
await page.goto(`/admin/users/${user.id}`);
await expect(page.locator('.user-name')).toHaveText('Nuevo Usuario');
});
Intercepcion de Red
await page.route('/api/users', route => {
route.fulfill({
status: 200,
body: JSON.stringify([{ id: 1, name: 'Mock User' }]),
});
});
const [response] = await Promise.all([
page.waitForResponse('/api/checkout'),
page.click('#pay-button'),
]);
expect(response.status()).toBe(200);
Multiples Contextos de Navegador
test('dos usuarios interactuan en tiempo real', async ({ browser }) => {
const adminContext = await browser.newContext();
const userContext = await browser.newContext();
const adminPage = await adminContext.newPage();
const userPage = await userContext.newPage();
await adminPage.goto('/admin/chat');
await adminPage.fill('#message', 'Hola usuario!');
await adminPage.click('#send');
await userPage.goto('/chat');
await expect(userPage.locator('.message')).toHaveText('Hola usuario!');
await adminContext.close();
await userContext.close();
});
Ejecutando Tests
npx playwright test # Todos los tests
npx playwright test tests/login.spec.ts # Archivo especifico
npx playwright test --project=firefox # Navegador especifico
npx playwright test --headed # Modo con interfaz
npx playwright test --ui # Modo interactivo
npx playwright test --debug tests/login.spec.ts # Debug
npx playwright show-report # Reporte HTML
Ejercicio: Construye un Suite de Tests con Playwright
Crea un suite completo de Playwright:
- Inicializa un proyecto con TypeScript
- Configura 3 proyectos de navegador (Chrome, Firefox, WebKit)
- Crea Page Objects para Login, Dashboard y Settings
- Escribe 8 tests: login (valido/invalido), navegacion, formulario, API + UI, mock de red, multi-viewport, comparacion de screenshot
- Configura traces y screenshots al fallar
- Ejecuta tests en paralelo en todos los navegadores
- Genera y revisa el reporte HTML
Puntos Clave
- El auto-waiting de Playwright elimina la mayoria de tests inestables por timing
- Los locators basados en rol son la estrategia mas resistente
- El Trace Viewer proporciona capacidades de debugging inigualables
- API testing incorporado permite mezclar setup rapido por API con verificacion UI
- Codegen graba interacciones y genera codigo de test
- Ejecucion paralela nativa en Chromium, Firefox y WebKit
- Los fixtures de Playwright se integran naturalmente con Page Object Model