Playwright: Estructura de pruebas y hooks

Este capítulo explica cómo se organizan las pruebas de Playwright, incluida la agrupación de pruebas, el control de ejecución y el uso de hooks del ciclo de vida.


test.describe() Agrupación de pruebas

test.describe()Se usa para agrupar pruebas relacionadas en grupos lógicos.

Ejemplo

// Ruta del archivo: tests/describe-demo.spec.ts
import { test, expect } from '@playwright/test';

// Primer nivel de agrupación
test.describe('Prueba de la página de inicio de EJEMPLO', () => {

  test('El título de la página es correcto', async ({ page }) => {
    await page.goto('https://www.example.com/');
    await expect(page).toHaveTitle(/EJEMPLO/);
  });

  test('La barra de navegación existe', async ({ page }) => {
    await page.goto('https://www.example.com/');
    // Verifica que el elemento de navegación existe
    await expect(page.locator('nav')).toBeVisible();
  });
});

// Se pueden definir varios bloques describe
test.describe('Prueba de la función de búsqueda', () => {

  test('El cuadro de búsqueda es visible', async ({ page }) => {
    await page.goto('https://www.example.com/');
    await expect(
      page.getByPlaceholder('Buscar')
    ).toBeVisible();
  });
});

El informe de pruebas se mostrarádescribepor grupos, facilitando la consulta de resultados.


describe anidado

test.describe()Se pueden anidar, formando una estructura de árbol:

Ejemplo

test.describe('Módulo de usuario', () => {

  test.describe('Función de inicio de sesión', () => {
    test('Inicio de sesión con cuenta y contraseña correctas', async ({ page }) => { /* ... */ });
    test('El inicio de sesión con contraseña incorrecta falla', async ({ page }) => { /* ... */ });
  });

  test.describe('Función de registro', () => {
    test('Registrarse con información correcta', async ({ page }) => { /* ... */ });
    test('El registro con un correo electrónico ya existente falla', async ({ page }) => { /* ... */ });
  });
});

test.skip() Saltar pruebas

test.skip()Se utiliza para saltar una prueba; las pruebas saltadas no se ejecutarán.

Ejemplo

// Saltar directamente (común para deshabilitar temporalmente pruebas de funcionalidad con errores)
test.skip('Prueba de funcionalidad aún no terminada', async ({ page }) => {
  // Esta prueba no se ejecutará
});

// Salto condicional (evaluado en tiempo de ejecución)
test('Saltar bajo condiciones específicas', async ({ page, browserName }) => {
  // Saltar en Firefox
  test.skip(browserName === 'firefox', 'Firefox no admite esta funcionalidad por ahora');

  // La lógica de la prueba solo se ejecuta en navegadores que no sean Firefox
  await page.goto('https://www.example.com/');
});

test.fail() Marcar fallo esperado

test.fail()Se utiliza para marcar una prueba que se sabe que fallará.

Ejemplo

// Marcado como fallo esperado (no se reportará como fallo de prueba)
test.fail('Bug conocido: la función de búsqueda aún no está implementada', async ({ page }) => {
  await page.goto('https://www.example.com/');
  // Esta aserción se espera que falle
  await expect(page.locator('.search-results')).toBeVisible();
});

// Si la prueba pasa inesperadamente, se informará como fallo
// Así te recuerda: 'Bug corregido, ya puedes quitar la marca test.fail'

test.fail()Su función es el marcado inverso: que la prueba falle = comportamiento esperado; que la prueba pase = anomalía (posiblemente haya que eliminar la marca).


test.only() Ejecutar solo la prueba actual

test.only()Se utiliza para ejecutar solo una prueba específica durante el desarrollo y la depuración, ignorando las demás pruebas del archivo.

Ejemplo

// Durante el desarrollo/depuración, ejecutar solo la prueba actual
test.only('Estoy depurando esta prueba', async ({ page }) => {
  // Solo esta prueba se ejecutará
  await page.goto('https://www.example.com/');
});

test('Esta prueba será ignorada', async ({ page }) => {
  // Debido a que hay un test.only() arriba, esta no se ejecutará
});

test.only()Es una herramienta de depuración y no debe enviarse al repositorio de código. Siplaywright.config.tsse configuraforbidOnly: true, CI lo detectaráonlyy hará fallar la compilación.


test.fixme() Marcar pendiente de corrección

test.fixme()ytest.skip()Similar, pero semánticamente significa que 'esta prueba necesita ser corregida'.

Ejemplo

// Marcado como pendiente de corrección (no se ejecutará)
test.fixme('El flujo de inicio de sesión necesita actualizarse debido a cambios en la API', async ({ page }) => {
  // Esta prueba no se ejecutará temporalmente
});

test.slow() Marcar prueba lenta

test.slow()Multiplica por 3 el tiempo de espera de la prueba.

Ejemplo

// Marcada como prueba lenta, el tiempo de espera se triplica
test.slow('Prueba de gran volumen de datos', async ({ page }) => {
  // El tiempo de espera predeterminado de esta prueba será de 90 segundos (30s × 3)
  // Apto para escenarios que requieren cargar grandes cantidades de datos o cálculos complejos
});

Hooks de prueba (Ganchos)

Las funciones hook te permiten ejecutar tareas de preparación y limpieza en las diferentes fases de las pruebas.

test.beforeEach() y test.afterEach()

beforeEachSe ejecuta antes de cada prueba,afterEachSe ejecuta después de cada prueba.

Ejemplo

// Ruta del archivo: tests/hooks-demo.spec.ts
import { test, expect } from '@playwright/test';

test.beforeEach(async ({ page }) => {
  // Antes de cada prueba, navega a la misma página
  await page.goto('https://www.example.com/');
});

test.afterEach(async ({ page }) => {
  // Después de cada prueba, se realiza una limpieza (por ejemplo, eliminar los datos creados)
  // Playwright limpia automáticamente el context del navegador,
  // Aquí la limpieza se refiere principalmente al estado del servidor
  console.log('Prueba completada, comenzando la limpieza...');
});

test('Primera prueba', async ({ page }) => {
  // page ya está en la página de inicio de EJEMPLO
  await expect(page).toHaveTitle(/EJEMPLO/);
});

test('Segunda prueba', async ({ page }) => {
  // page también está ya en la página de inicio de EJEMPLO
  // Este es un context completamente nuevo; las cookies/el almacenamiento de la prueba anterior no persisten
  await expect(page.locator('nav')).toBeVisible();
});

test.beforeAll() y test.afterAll()

beforeAllEnEn el ámbito actualse ejecuta una vez antes de todas las pruebas,afterAllse ejecuta una vez después de todas las pruebas.

Ejemplo

test.describe('Gestión de usuarios', () => {
  test.beforeAll(async ({ browser }) => {
    // Crear un usuario de prueba antes de todas las pruebas (solo se ejecuta una vez)
    // Nota: beforeAll no puede usar el fixture page
  });

  test.afterAll(async ({ browser }) => {
    // Eliminar el usuario de prueba después de todas las pruebas (solo se ejecuta una vez)
  });

  test('Ver la lista de usuarios', async ({ page }) => { /* ... */ });
  test('Editar la información del usuario', async ({ page }) => { /* ... */ });
});

beforeAllyafterAllno puede acceder alpagefixture, porque page es independiente para cada prueba. Si necesitas manipular la página, usabeforeEach。


Ámbito y orden de ejecución de los hooks

El ámbito de los hooks depende de su ubicación:

Ejemplo

// Hooks a nivel de archivo: se aplican a todo el archivo

test.beforeEach(async () => {
  console.log('beforeEach a nivel de archivo');
});

test.describe('Grupo A', () => {
  // Hooks a nivel de grupo: solo se aplican al Grupo A
  test.beforeEach(async () => {
    console.log('beforeEach del Grupo A');
  });

  test('Prueba A1', async () => { /* ... */ });
  test('Prueba A2', async () => { /* ... */ });
});

test.describe('Grupo B', () => {
  // El Grupo B no tiene hooks propios, solo se aplican los hooks a nivel de archivo
  test('Prueba B1', async () => { /* ... */ });
});

Orden de ejecución: los hooks externos se ejecutan primero, luego los internos.

Para A1 y A2: primero se imprime"文件级 beforeEach", luego se imprime"分组 A 的 beforeEach"。

Para B1: solo se imprime"文件级 beforeEach"。

Otras extensiones