Volver al inicio

Estabilizando Pruebas de Playwright en CI

El artículo describe la metodología para estabilizar las pruebas de Playwright en CI usando Dependency Projects, web-first asserts y selección adecuada de localizadores. Se proporcionan ejemplos de configuración y código para proyectos empresariales.

Playwright: Eliminando Inestabilidades en CI con Dependency Projects
Advertisement 728x90

Estabilizar pruebas de Playwright en CI: Proyectos de dependencia y afirmaciones web-first

Las dependencias encadenadas en Playwright evitan la ejecución de pruebas en entornos inestables, ahorrando recursos de CI y reduciendo falsos positivos.

Primero se realiza la autenticación mediante API con persistencia del estado de almacenamiento. Luego, una verificación de salud comprueba la disponibilidad de la API. Solo después de esto se ejecutan las pruebas principales de interfaz.

Ventajas frente a globalSetup:

Google AdInline article slot
  • Traces completos con solicitudes de red, capturas de pantalla y registros de consola.
  • Comportamiento "fail-fast": si el setup falla, los proyectos dependientes se detienen de inmediato.
  • Aislamiento: cada etapa puede probarse individualmente usando npx playwright test --project=auth-setup.

Configuración en playwright.config.ts:

export default defineConfig({
  projects: [
    {
      name: 'auth-setup',
      testMatch: /.*\.auth\.setup\.ts/,
    },
    {
      name: 'healthcheck',
      testMatch: /.*\.health\.setup\.ts/,
      dependencies: ['auth-setup'],
    },
    {
      name: 'chromium',
      use: { ...devices['Desktop Chrome'] },
      dependencies: ['healthcheck'],
    },
  ],
});

La autenticación basada en API reduce drásticamente el tiempo de configuración: una solicitud POST tarda entre 50 y 100 ms frente a los 2–5 segundos que requiere el inicio de sesión por interfaz.

Ejemplo de prueba auth-setup:

Google AdInline article slot
test('setup', async ({ request }) => {
  await request.post('/api/login', { data: { user, pass } });
  await request.storageState({ path: '.auth/user.json' });
});

Los gráficos de dependencia eliminan condiciones de carrera durante las ejecuciones paralelas de pruebas.

Elegir localizadores con inteligencia

La selección de localizadores afecta directamente la resiliencia de las pruebas ante cambios en la interfaz. Sepáralos según su propósito: usa getByTestId para acciones y getByRole o getByLabel para afirmaciones.

Mejores prácticas:

Google AdInline article slot
  • Acciones (clic, entrada): page.getByTestId('add-to-cart-button').click() — independiente del texto o estilo.
  • Validación de texto/estado: expect(page.getByRole('heading')).toHaveText('Mi cuenta').
  • Campos de entrada: page.getByLabel('Correo electrónico').fill('[email protected]').
  • Contadores: expect(locator).toHaveText('3').

Los selectores CSS solo deben usarse como último recurso. Capacitar al equipo en el uso adecuado de localizadores rinde beneficios diez veces mayores a gran escala.

Afirmaciones web-first vs. inestabilidad

Las comprobaciones de instantáneas como await loc.isVisible() son propensas a condiciones de carrera. Las afirmaciones web-first con polling ofrecen mayor estabilidad.

Comparación de afirmaciones:

| Comprobación | Instantánea (sin espera) | Web-first (con polling) |

|---------------|--------------------------|--------------------------|

| Visibilidad | await loc.isVisible() | expect(loc).toBeVisible() |

| Texto | await loc.textContent() | expect(loc).toHaveText('Texto') |

| Cantidad | await loc.count() | expect(loc).toHaveCount(3) |

| Atributo | await loc.getAttribute('href') | expect(loc).toHaveAttribute('href', '/ruta') |

| Checkbox | await loc.isChecked() | expect(loc).toBeChecked() |

| Estado | await loc.isEnabled() | expect(loc).toBeEnabled() |

El polling intenta cada 100 ms hasta el tiempo máximo, ignorando parpadeos temporales en la interfaz.

Hidratación y force: true

El problema de desincronización en aplicaciones SSR/SSG ocurre cuando el marcado renderizado por el servidor existe pero aún no se han adjuntado los manejadores de JavaScript.

Esperar marcadores de hidratación:

  • await page.waitForSelector('.hydrated', { state: 'attached' })
  • await expect(page.locator('#global-loader')).toBeHidden()

force: true desactiva las comprobaciones de accionabilidad (visible, estable, habilitado, recepción de eventos), convirtiendo la prueba en un script de DOM puro. Úsalo con moderación y siempre con un comentario — ideal para casos extremos como campos de archivo.

Conclusiones clave

  • Proyectos de dependencia crean un grafo de dependencias que evita que las pruebas se ejecuten en entornos no listos.
  • Afirmaciones web-first con polling eliminan el 80% de la inestabilidad causada por condiciones de carrera.
  • Separar localizadores por rol aumenta la resistencia ante reestructuraciones de interfaz.
  • Autenticación por API acelera la configuración entre 20 y 50 veces respecto al inicio de sesión por interfaz.
  • Traces en lugar de capturas brindan contexto completo ante fallos en CI.

— Editorial Team

Advertisement 728x90

Leer después