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
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('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
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
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
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
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
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
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.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
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"。