Codegen genera un .spec.ts ejecutable en el tiempo que tardas en hacer clic por un flujo una sola vez, pero el test generado se llama 'test', contiene las credenciales que escribiste, y casi nunca tiene más de una aserción. Tratarlo como código terminado es el error más común. Esta guía cubre cómo ejecutar codegen, cómo elegir mejores locators desde las opciones que ofrece el Inspector, cómo limpiar el output antes de hacer commit, y dónde codegen no puede ayudarte para que sepas qué escribir a mano.

Qué genera codegen exactamente

Codegen es el grabador de tests integrado de Playwright. Lo inicias con un solo comando, interactúas con una página en el navegador que se abre, y un panel al costado escribe el TypeScript (o JavaScript, Python, Java o C#) correspondiente mientras avanzás.

Lo que obtenés al final es un archivo .spec.ts que contiene:

  • Llamadas a page.goto() para cada navegación
  • Métodos de acción como click(), fill(), check() y selectOption() por cada interacción que realizaste
  • Locators para cada elemento que tocaste, elegidos automáticamente por la estrategia de locators de Playwright
  • Una aserción básica al final si usaste la herramienta de aserciones del inspector

El código generado es ejecutable de inmediato. Lo pegas en un archivo de test y lo corres con npx playwright test; en la mayoría de los casos pasa a la primera. El valor no está en que el output sea perfecto, sino en que tenés un esqueleto funcionando en menos de dos minutos en lugar de treinta.

Ejecutar codegen contra lab.becomeqa.com

Inicia codegen apuntando a cualquier URL:

npx playwright codegen https://lab.becomeqa.com

Se abren dos ventanas al mismo tiempo. La primera es un navegador Chromium estándar mostrando la página objetivo. La segunda es el Playwright Inspector: una ventana separada con un panel de código, un botón de grabación y un selector de locators.

No necesitás un proyecto especial para esto. Codegen funciona completamente fuera de un proyecto de Playwright. Si estás en un directorio de proyecto, el código generado respeta el lenguaje configurado. Si no, usa TypeScript por defecto.

Para generar código en un lenguaje específico:

# JavaScript
npx playwright codegen --target javascript https://lab.becomeqa.com

# Python
npx playwright codegen --target python https://lab.becomeqa.com

# Java
npx playwright codegen --target java https://lab.becomeqa.com

Para apuntar a un navegador específico en lugar del Chromium por defecto:

npx playwright codegen --browser firefox https://lab.becomeqa.com
npx playwright codegen --browser webkit https://lab.becomeqa.com

El flag --browser es útil cuando sospechas que los locators difieren entre Chromium y WebKit, o cuando estás construyendo un test que apunta a comportamiento específico de Firefox.

La interfaz de codegen: tres herramientas que necesitás conocer

El Playwright Inspector te da tres cosas que vale la pena entender antes de empezar a grabar.

El botón Record inicia y detiene la grabación. Cuando está activo (rojo), cada interacción en la ventana del navegador se captura como código. Haz clic de nuevo para pausar sin cerrar la sesión. Esto te permite navegar manualmente a un estado difícil de alcanzar (como abrir un modal o navegar varios pasos) y luego reanudar la grabación desde ahí. El selector de locators (el ícono de mira) pone el navegador en modo inspección. Mueves el cursor sobre cualquier elemento y el Inspector te muestra el locator que Playwright generaría, junto con una vista previa de cuántos elementos coinciden con ese locator. Verde significa un solo resultado. Amarillo significa varios resultados, así que ese locator es ambiguo y no debería usarse en un test. El panel de aserciones (el ícono de checkbox) te permite agregar aserciones mientras grabas. Haces clic, luego haces clic en un elemento del navegador, y codegen inserta una aserción toBeVisible() en el código. También puedes asertar contenido de texto o estado de checked desde el dropdown que aparece. Esta es una de las funciones más subutilizadas: los principiantes suelen grabar acciones pero se olvidan de asertar algo.

Por qué codegen elige getByRole primero

Cuando haces clic en un botón llamado "Login", codegen no genera page.locator('button.login-btn'). Genera page.getByRole('button', { name: 'Login' }).

Es intencional. La estrategia de locators de Playwright los prioriza en este orden:

1. getByRole: coincide por rol ARIA y nombre accesible

2. getByLabel: para inputs asociados a un label

3. getByPlaceholder: para inputs con texto de placeholder

4. getByText: para elementos no interactivos

5. getByTestId: para elementos con atributo data-testid

6. CSS o XPath: último recurso

La razón por la que getByRole va primero es la resiliencia. La clase CSS de un botón puede cambiar cuando un diseñador actualiza el stylesheet. Su posición en el DOM puede variar cuando alguien agrega una nueva función. Pero un botón llamado "Login" casi siempre sigue llamándose "Login": cambiarlo rompería la interfaz para los usuarios reales también. Los tests construidos sobre locators accesibles son más estables porque se rompen por las mismas razones que los usuarios reales notarían.

Cuando veas que codegen genera algo como page.locator('.btn-primary'), es señal de que el elemento no tiene un nombre accesible adecuado. Vale la pena pausar y preguntarse si se puede agregar un atributo data-testid a ese elemento.

Si codegen cae a un selector CSS, revisá el elemento en DevTools. La solución suele ser agregar aria-label o asegurarse de que el elemento label esté correctamente asociado a su input. Mejor accesibilidad y mejores locators de test vienen de la misma fuente.

Grabar un flujo de login completo

Así se graba un test de login real contra lab.becomeqa.com, paso a paso.

Inicia codegen:

npx playwright codegen https://lab.becomeqa.com

Una vez que ambas ventanas estén abiertas y la grabación activa, ejecuta esta secuencia en el navegador:

1. Haz clic en el botón Login de la navegación

2. Completa el campo de email con una cuenta de prueba

3. Completa el campo de contraseña

4. Haz clic en Submit

5. Espera a que cargue el dashboard

6. Usa el selector de aserciones para asertar que algo del dashboard es visible

Después de completar esos pasos, el panel del Inspector muestra algo parecido a esto:

import { test, expect } from '@playwright/test';

test('test', async ({ page }) => {
  await page.goto('https://lab.becomeqa.com/');
  await page.getByRole('button', { name: 'Login' }).click();
  await page.getByLabel('Email').fill('usuario@ejemplo.com');
  await page.getByLabel('Password').fill('contraseña123');
  await page.getByRole('button', { name: 'Submit' }).click();
  await expect(page.getByText('Mis Ítems de Viaje')).toBeVisible();
});

Haz clic en el botón copiar del Inspector, crea un archivo en tests/login.spec.ts, y pégalo. Ejecutalo:

npx playwright test tests/login.spec.ts --project=chromium

Pasa. Tienes un test funcionando en el tiempo que tardó hacer clic por el flujo de login una vez.

Limpiar el código generado

El código generado funciona, pero no es de calidad para producción. Tres cosas necesitan atención antes de que pertenezca a una suite de tests real.

Credenciales hardcodeadas

El código generado contiene el email y la contraseña reales que escribiste. No pertenecen al control de versiones. Muévelos a variables de entorno:

import { test, expect } from '@playwright/test';

test('el usuario puede iniciar sesión', async ({ page }) => {
  await page.goto('/');
  await page.getByRole('button', { name: 'Login' }).click();
  await page.getByLabel('Email').fill(process.env.TEST_EMAIL!);
  await page.getByLabel('Password').fill(process.env.TEST_PASSWORD!);
  await page.getByRole('button', { name: 'Submit' }).click();
  await expect(page.getByText('Mis Ítems de Viaje')).toBeVisible();
});

Si tienes una baseURL en playwright.config.ts, también reemplaza la URL hardcodeada en page.goto() por '/'.

El nombre del test

Codegen nombra cada test 'test'. Renómbralo para describir el comportamiento que se verifica, como 'el usuario puede iniciar sesión con credenciales válidas'.

Aserciones faltantes

Codegen solo graba acciones y las aserciones que agregaste explícitamente. Un test de login debería asertar más de una cosa: no solo que aparece el texto "Mis Ítems de Viaje", sino también que la URL cambió, o que el menú de usuario muestra el email correcto. Agrégalas manualmente.

Locators repetidos

Si grabaste un flujo que usa el mismo locator cinco veces, extráelo a una variable:

const emailInput = page.getByLabel('Email');
await emailInput.fill(process.env.TEST_EMAIL!);

Esto es menor a nivel de test, pero se vuelve esencial cuando los mismos locators aparecen en múltiples archivos de test. Ese es el momento de pasar al Page Object Model. No lo hagas antes de necesitarlo.

Tratá el código generado como un primer borrador que te ahorra tiempo encontrando locators, no como tests terminados. Planificá 5 a 10 minutos de edición por cada test generado antes de hacer commit.

Grabar en distintos navegadores y guardar el output en un archivo

Codegen soporta los tres motores de navegador de Playwright. Por defecto usa Chromium. Cambia a Firefox o WebKit cuando necesitas locators que funcionen entre motores o cuando estás depurando comportamiento específico de un navegador:

npx playwright codegen --browser webkit https://lab.becomeqa.com

También puedes guardar el código generado directamente en un archivo en lugar de copiarlo desde el panel del Inspector:

npx playwright codegen --output tests/login.spec.ts https://lab.becomeqa.com

Con --output, el archivo se escribe cuando cierras la ventana del Inspector. Si el archivo ya existe, se sobreescribe. Combinalo con un lenguaje destino específico para generar archivos de test en cualquier stack soportado:

npx playwright codegen --target javascript --output tests/login.spec.js https://lab.becomeqa.com

Para equipos que usan emulación de dispositivos, codegen soporta --device para simular viewports móviles:

npx playwright codegen --device "iPhone 13" https://lab.becomeqa.com

Esto abre el navegador con el tamaño de pantalla del iPhone 13 y el user agent correcto. El código generado incluye devices['iPhone 13'] en las opciones del contexto.

Usar codegen como explorador de locators (sin grabar tests)

Uno de los usos más prácticos de codegen no involucra grabar un test completo. A veces solo necesitás encontrar el locator correcto para un elemento específico sin querer inspeccionar el DOM manualmente.

Inicia codegen, haz clic en el selector de locators, y mueve el cursor sobre el elemento que te interesa. El Inspector muestra el locator en tiempo real. También muestra cuántos elementos coinciden: información crítica antes de comprometer un locator a un test.

npx playwright codegen https://lab.becomeqa.com

Una vez que el navegador esté abierto, presiona el botón de grabación para detenerla y no generar código que no necesitas. Cambia al modo selector de locators y pasa el cursor sobre los elementos. El Inspector actualiza el locator en tiempo real mientras te movés entre elementos. Podés escribir en el campo del locator para probar variaciones y ver cuántos elementos coinciden.

Este flujo reemplaza horas de prueba y error en el test runner. Validás un locator antes de escribir el test, no después de que falle.

Los límites de codegen: qué no puede grabar

Codegen maneja la mayoría de las interacciones de usuario: clics, llenado de formularios, navegación, dropdowns, checkboxes, radio buttons. Hay varias categorías que maneja mal o directamente no puede manejar.

Subida de archivos

Codegen no puede grabar page.setInputFiles(). Cuando haces clic en un input de archivo y seleccionas un archivo desde tu sistema, codegen puede capturar el clic pero no la selección del archivo en sí. Tienes que escribir el código de subida de archivos manualmente.

Drag and drop

Los eventos de drag-and-drop de HTML no se traducen bien a grabaciones de codegen. El código generado puede mostrar un clic sin el movimiento de arrastre, lo que significa que la interacción silenciosamente no hace lo que esperas. Usá page.dragAndDrop() o simulá los eventos individuales mousedown, mousemove y mouseup para interacciones de arrastre confiables.

Esperas complejas

Codegen graba acciones en el momento en que las realizas. No graba el pensamiento implícito que hacés como humano ("esperé a que desapareciera el spinner antes de hacer clic"). En entornos lentos o poco confiables, los tests generados pueden fallar porque se ejecutan más rápido de lo que la interfaz espera. Agregá esperas explícitas donde el flujo las requiera:

await page.waitForLoadState('networkidle');
await expect(page.getByRole('progressbar')).toBeHidden();

Flujos de múltiples pestañas

Cuando una acción abre una nueva pestaña del navegador, codegen no la sigue automáticamente. Necesitás manejar las páginas nuevas explícitamente usando context.waitForEvent('page'). Codegen puede perderse la nueva pestaña por completo.

Estados autenticados

Codegen no sabe sobre autenticación almacenada. Si querés que los tests empiecen ya con sesión iniciada, usá storageState de Playwright para guardar las cookies de sesión después de iniciar sesión una vez, y luego cargá ese estado al inicio de cada test. Codegen puede ayudarte a grabar el login una vez, pero el patrón de storage state necesita configurarse manualmente.

Flujos OAuth y login de terceros

Cualquier flujo que redirecciona a un proveedor de identidad externo (Google, GitHub, Microsoft) es difícil de grabar con codegen porque los locators existen en una página de terceros que puede que no controles. Estos flujos necesitan manejo separado y a menudo requieren mockear el callback de OAuth en lugar de pasar por el proveedor real.

FAQ

¿El código de codegen es suficientemente bueno para hacer commit directamente?

Casi nunca. Es un punto de partida rápido, no un test terminado. Siempre renombra el test, elimina las credenciales hardcodeadas, verifica que las aserciones sean significativas, y revisa que los locators coincidan con la estructura de accesibilidad de la página.

¿Puedo usar codegen en una URL de localhost?

Sí. npx playwright codegen http://localhost:3000 funciona exactamente igual. Si tu aplicación requiere autenticación para llegar a la página que querés grabar, podés iniciar sesión manualmente antes de presionar el botón de grabación.

Codegen generó un selector CSS en lugar de getByRole. ¿Debería usarlo?

Solo si no hay mejor opción. Un selector CSS como .item-card:nth-child(2) se romperá en el momento que cambie el layout de la página. Intentá entender por qué Playwright cayó a CSS: el elemento probablemente no tiene un nombre accesible. Si no podés agregarlo, getByTestId con un atributo data-testid es la siguiente mejor opción.

¿Codegen ralentiza el navegador?

No hay diferencia medible. La grabación ocurre en el proceso del Inspector, no dentro del navegador.

¿Puedo pausar en medio de una grabación y navegar manualmente?

Sí. Haz clic en el botón de grabación para pausar, navega al estado que necesitas, y haz clic de nuevo para reanudar. Solo se capturan las interacciones mientras la grabación está activa.

¿Por qué codegen generó page.locator('text=Submit') en lugar de getByRole?

Esto pasa cuando Playwright no puede encontrar un locator confiable basado en rol. Cae a coincidencia por texto. Revisa si el elemento es un botón con nombre accesible; debería generar getByRole('button', { name: 'Submit' }) para un elemento button estándar.

→ See also: Locators de Playwright: getByRole, getByLabel, getByText, getByTestId Comparados | Empezando con Playwright: Tus Primeros Tests en 30 Minutos | Configuración de VS Code para Playwright: Extensiones, Ajustes y Productividad