Playwright: reorganización del framework — de archivos didácticos a estructura de producción

9 specs didácticos separados en learning/, 2 tests de producción en e2e/ con fixtures y POM. Refactor real: qué cambió, qué se rompió, resultado.

Carpeta tests en VS Code mostrando subcarpetas e2e con dos specs y learning con nueve specs didácticos, auth.setup.ts fuera de ambas
La separación: e2e/ para producción, learning/ para la serie, auth.setup.ts compartido.

Contexto: por qué reorganizar ahora

Hasta el Post 10 Testing de grilla en Playwright, los tests vivían todos en la misma carpeta:

tests/
├── serenity/
│   └── auth.setup.ts
├── example.spec.ts
├── saucedemo.spec.ts
├── serenity-assertions.spec.ts
├── serenity-clientes-excel.spec.ts
├── serenity-data-driven.spec.ts
├── serenity-fixtures.spec.ts
├── serenity-grilla-interacciones.spec.ts
├── serenity-locators.spec.ts
└── serenity-storagestate.spec.ts

9 archivos .spec.ts, todos al mismo nivel. Cada uno enseña un concepto: locators, assertions, fixtures, storageState, data-driven, grilla. Eso tenía sentido mientras escribía la serie — un post, un archivo, un tema.

Pero como framework esto no funciona. Si alguien clona el repo y corre npx playwright test, le caen encima 9 specs didácticos mezclados, con nombres que no dicen nada sobre qué funcionalidad testean. No hay separación entre "estoy aprendiendo esto" y "esto es un test real".

Decidí separar.


La separación: learning/ vs e2e/

La idea es sencilla:

tests/learning/ — Los specs didácticos de la serie. Cada archivo corresponde a un post, muestra un concepto. Quedan como referencia y documentación. No corren por defecto.

tests/e2e/ — Los tests de producción. Usan todo lo aprendido: POM, fixtures, storageState, data-driven, assertions modernas. Son lo que correría en una empresa.

Carpeta tests en VS Code mostrando subcarpetas e2e con dos specs y learning con nueve specs didácticos, auth.setup.ts fuera de ambas
La separación: e2e/ para producción, learning/ para la serie, auth.setup.ts compartido.

La diferencia no es solo de carpetas. Es de cómo se escriben.


Learning vs E2E: qué cambia en el código

Cómo se hacía en los learning specs

Cada test instanciaba los Page Objects manualmente:

import { test, expect } from '@playwright/test';
import { LoginPage } from '../pages/LoginPage';
import { DashboardPage } from '../pages/DashboardPage';

test('login válido', async ({ page }) => {
    const loginPage = new LoginPage(page);
    const dashboardPage = new DashboardPage(page);

    await loginPage.goto();
    await loginPage.login('admin', 'serenity');
    await dashboardPage.verificarVisible();
});

Funciona. Pero hay repetición: cada test que necesite loginPage tiene que hacer new LoginPage(page). En 5 tests no molesta. En 50, sí.

Cómo se hace en los e2e specs

Los e2e usan los fixtures que armé en el Post 5. El Page Object viene inyectado:

import { test, expect } from '../../fixtures/test-fixtures';

test('login válido', async ({ loginPage, dashboardPage }) => {
    await loginPage.goto();
    await loginPage.login('admin', 'serenity');
    await dashboardPage.verificarVisible();
});

La lógica del test es la misma. Lo que cambia es de dónde vienen loginPage y dashboardPage. En vez de crearlos manualmente, Playwright los inyecta a través del fixture system. Menos código repetido, más fácil de mantener.

Y otro detalle: los e2e usan baseURL del config. En vez de hardcodear page.goto('https://demo.serenity.is/'), hacen page.goto('/'). Si mañana cambio de entorno, cambio una línea en el config y no toco ningún test.


Los tests de producción

login.spec.ts

Combina lo que estaba en serenity-data-driven.spec.ts: login positivo y login negativo con data-driven.

Archivo login.spec.ts en VS Code con import de fixtures, array de credenciales inválidas, describe de login positivo y negativo data-driven
login.spec.ts — 5 tests, un solo import de fixtures. Sin new LoginPage(page) en ningún lado.

5 tests: 2 positivos (login manual + click con credenciales precargadas) y 3 negativos data-driven (password incorrecta, usuario incorrecto, campos vacíos).

Todos usan test.use({ storageState: { cookies: [], origins: [] } }) para anular la autenticación automática — necesitamos probar el login real, no arrancar ya logueados.

clientes.spec.ts

Combina lo que estaba repartido en dos archivos separados (serenity-clientes-excel.spec.ts + serenity-grilla-interacciones.spec.ts). Ahora es un solo archivo organizado por describe:

Parte superior de clientes.spec.ts mostrando beforeEach con fixtures, validación contra Excel con soft assertions y sección de ordenamiento
clientes.spec.ts — beforeEach con fixtures, validación Excel campo a campo, ordenamiento por ID y Empresa.
Parte inferior de clientes.spec.ts mostrando secciones de filtros Select2 con Argentina y Buenos Aires y búsqueda con ALFKI y texto inexistente
Filtros Select2 y búsqueda. Todo en un archivo, organizado por describe.

4 secciones, 8 tests:

  • Validación contra Excel — los 91 clientes campo a campo con soft assertions
  • Ordenamiento — ID asc/desc, Empresa asc/desc
  • Filtros Select2 — filtro por país, filtro combinado, limpiar filtros
  • Búsqueda — buscar ALFKI, buscar texto inexistente

La navegación al módulo de Clientes está en beforeEach usando fixtures:

test.beforeEach(async ({ page, dashboardPage, clientesPage }) => {
    await page.goto('/', { timeout: 15000 });
    await dashboardPage.verificarVisible();
    await dashboardPage.irAClientes();
    await clientesPage.verificarVisible();
});

Cada test recibe clientesPage ya listo. No hay new ClientesPage(page) en ningún lado.


El config: una línea

El cambio en playwright.config.ts es mínimo:

export default defineConfig({
    testDir: './tests',
    testIgnore: ['**/learning/**'],   // ← esta línea
    // ... resto igual
});
Archivo playwright.config.ts en VS Code con la línea testIgnore learning resaltada en la línea 5 junto al resto de la configuración
Una línea: testIgnore. Los learning specs dejan de correr por defecto.

testIgnore le dice a Playwright: todo lo que esté dentro de learning/ no lo corras. Así npx playwright test ejecuta solo los e2e y el auth.setup.

Los learning specs siguen en el repo. Siguen funcionando. Pero no corren a menos que los llames explícitamente.


El refactor: lo que tuve que ajustar

Mover los archivos fue la parte fácil. Lo que llevó un poco más de atención:

Imports rotos. Al mover los specs un nivel más abajo (de tests/ a tests/learning/), todos los paths relativos se rompieron. '../pages/LoginPage' pasó a ser '../../pages/LoginPage'. TypeScript los marca en rojo al instante, así que encontrar los rotos fue trivial. Arreglarlos fue mecánico pero había que hacerlo en los 9 archivos.

Path del Excel. El test de validación contra Excel usa path.join(__dirname, '..', 'test-data', ...). Al moverse un nivel, el path cambió: path.join(__dirname, '..', '..', 'test-data', ...). Esto aplica tanto al learning como al e2e.

Nada complejo. Pero si no lo hacés, nada compila.


Resultado: 34 passed, 3 failed

Reporte HTML de Playwright mostrando clientes.spec.ts con 3 tests de Excel fallidos en rojo y 21 tests de ordenamiento filtros y búsqueda verdes
clientes.spec.ts: 21 passed, 3 failed. Los fallos son las discrepancias conocidas del Excel.

37 tests en total × 3 browsers:

  • auth.setup → 1 passed
  • login.spec.ts → 15 passed (5 tests × 3 browsers)
  • clientes.spec.ts → 21 passed, 3 failed (8 tests × 3 browsers, el de Excel falla en los 3)
Reporte HTML de Playwright mostrando login.spec.ts con 15 tests verdes en chromium firefox y webkit incluyendo login positivo y negativo
login.spec.ts: 15/15. Login positivo, credenciales precargadas y 3 casos negativos × 3 browsers.

Login: 15/15. Los fixtures inyectan loginPage y dashboardPage correctamente. El data-driven genera un test por cada caso de credenciales inválidas. Todo funciona igual que en el learning spec.

Reporte completo de clientes.spec.ts mostrando los 24 tests en tres browsers con 3 fallos de Excel y 21 tests de grilla verdes
Vista completa de clientes.spec.ts: 8 tests × 3 browsers = 24. Los 3 rojos son Excel.

Clientes: 21/24. Los 3 fallos son el test de validación contra Excel, uno por browser. Los mismos errores que ya documenté en el Post 9:

  • EASTCs — el Excel tiene "EASTCs" con s minúscula, la grilla tiene "EASTC". Typo intencional en el dataset.
  • FISSA — el Excel dice "Accounting Managers" (plural), la grilla dice "Accounting Manager" (singular). Otro typo intencional.
  • CENTC — el Excel dice "Mexicos", la grilla dice "Mexico". Tercer typo intencional.
  • WOLZA — el doble espacio en "Wolski Zajazd" del Excel. El bug real que Selenium nunca detectó y que Playwright sí encontró.

Los tests están funcionando exactamente como deben: detectan las discrepancias entre la fuente de datos y la aplicación.

Detalle de errores del test de Excel mostrando EASTCs no encontrado, FISSA título plural, CENTC país Mexicos y WOLZA doble espacio
Los 4 errores: EASTCs (typo de ID), FISSA (plural), CENTC (Mexicos), WOLZA (doble espacio). Todos esperados.

Estructura final

PLAYWRIGHT-TYPESCRIPT-FRAMEWORK/
├── fixtures/
│   └── test-fixtures.ts
├── pages/
│   ├── ClientesPage.ts
│   ├── DashboardPage.ts
│   └── LoginPage.ts
├── test-data/
│   └── clientes-data.xlsx
├── tests/
│   ├── auth.setup.ts
│   │   
│   ├── e2e/
│   │   ├── login.spec.ts
│   │   └── clientes.spec.ts
│   └── learning/
│       ├── example.spec.ts
│       ├── saucedemo.spec.ts
│       ├── serenity-assertions.spec.ts
│       ├── serenity-clientes-excel.spec.ts
│       ├── serenity-data-driven.spec.ts
│       ├── serenity-fixtures.spec.ts
│       ├── serenity-grilla-interacciones.spec.ts
│       ├── serenity-locators.spec.ts
│       └── serenity-storagestate.spec.ts
├── types/
│   └── Cliente.ts
├── utils/
│   └── excelReader.ts
└── playwright.config.ts
Estructura completa del proyecto Playwright en VS Code con carpetas auth fixtures pages test-data tests con e2e y learning types y utils
Estructura final del framework. Cada carpeta tiene un rol claro.

Los learning specs quedan como documentación viva de la serie. Cada archivo tiene su post correspondiente, el código funciona, los links del blog siguen apuntando a archivos que existen en el repo.

Los e2e specs son lo que importa: login.spec.ts y clientes.spec.ts combinan POM + fixtures + storageState + data-driven + soft assertions. Si alguien quiere ver cómo se ve un framework Playwright armado para producción, mira e2e/. Si quiere entender cómo se llegó ahí, lee learning/.


Estado actual

El framework tiene dos capas claras. Los tests de producción usan fixtures, baseURL, y agrupan por funcionalidad. Los didácticos quedan como referencia sin estorbar.

npx playwright test corre 37 tests en 3 browsers. 34 pasan. 3 fallan por discrepancias conocidas en el dataset de Excel.

Próximo post: ejecución paralela — cómo Playwright maneja workers y paralelismo, y cómo configurarlo.

🔗 Todo el código de esta serie está en: github.com/cesarbeassuarez/playwright-typescript-framework