Ir al contenido

Pasos y adjuntos de Playwright

Los pasos y los archivos de cada intento van con su resultado en Probara. Escribe los pasos con el test.step de Playwright, activa las capturas, los vídeos y las trazas en use como siempre, y el reporter los envía: no hay nada que activar en el reporter.

Los pasos de una prueba se muestran bajo su resultado en Probara, anidados tal como se ejecutaron, cada uno con su estado, su duración y su error.

tests/checkout.spec.ts
import { expect, test } from '@playwright/test';
test('checks out', async ({ page }) => {
await test.step('Open the cart', async () => {
await page.goto('https://shop.example.com/cart');
});
await test.step('Pay', async () => {
await test.step('Enter the card', async () => {
await page.getByLabel('Card number').fill('4242 4242 4242 4242');
});
await test.step('Confirm', async () => {
expect(await Promise.resolve('declined')).toBe('paid');
});
});
});
[
{
"status": "failed",
"steps": [
{ "action": "Open the cart", "status": "passed" },
{
"action": "Pay",
"status": "failed",
"steps": [
{ "action": "Enter the card", "status": "passed" },
{ "action": "Confirm", "status": "failed" }
]
}
]
}
]
Qué se ejecutóEn el resultado
Un test.stepUn paso, con sus hijos
Un hook (beforeEach, afterEach, Before Hooks…) que ejecutó un test.stepUn paso con el nombre del hook, que contiene esos pasos
Un hook o un fixture sin test.stepNada: sus hijos test.step, si los hay, suben un nivel
Llamadas a expect, a la API de Playwright (page.click…), fixturesNada: son detalles internos de Playwright, no tus pasos

El estado de un paso es failed cuando lanzó un error (sus padres fallan con él), skipped para test.step.skip() y passed en los demás casos. Su error (mensaje y stack) va con él, y su duración es la de Playwright.

Un hook que ejecuta pasos aparece como un paso propio, así la preparación y la limpieza quedan separadas de la prueba:

tests/orders.spec.ts
import { test } from '@playwright/test';
test.beforeEach(async () => {
await test.step('Sign in', async () => {});
});
test('lists the orders', async () => {
await test.step('Open the orders', async () => {});
});
[
{
"steps": [
{
"action": "Before Hooks",
"steps": [{ "action": "beforeEach hook", "steps": [{ "action": "Sign in" }] }]
},
{ "action": "Open the orders" }
]
}
]

Los pasos de un resultado registran lo que se ejecutó. Los pasos de un caso son su especificación: una acción, el resultado esperado y los datos de prueba. Decláralos con probara.step(action, expected, data) como título de un test.step; el paso se ejecuta como siempre, y el caso que crea el informe lo incorpora:

tests/refund.spec.ts
import { test } from '@playwright/test';
import { probara } from '@probara/playwright-reporter';
test('refunds an order', async () => {
await test.step(
probara.step('Open the order', 'The order is shown', 'order=1042'),
async () => {},
);
await test.step(probara.step('Refund it', 'The order is refunded'), async () => {
await test.step('Confirm the dialog', async () => {});
});
});
[
{
"steps": [
{ "action": "Open the order", "expected": "The order is shown", "data": "order=1042" },
{
"action": "Refund it",
"expected": "The order is refunded",
"steps": [{ "action": "Confirm the dialog" }]
}
],
"case": {
"steps": [
{ "action": "Open the order", "expected": "The order is shown", "data": "order=1042" },
{ "action": "Refund it", "expected": "The order is refunded" }
]
}
}
]
  • probara.step('Pay') devuelve Pay [probara:1]: los informes de Playwright muestran ese título, y el reporter lee la referencia corta y envía Pay.
  • Los pasos del caso son los pasos probara.step() que se ejecutaron y no están dentro de otro, en el orden en que empezaron. Un test.step normal es solo un paso del resultado: los pasos anidados como Confirm the dialog describen cómo funciona la prueba, no lo que especifica.
  • Como cualquier campo del caso, solo se aplican cuando el informe crea el caso (solo casos creados).

Cada archivo de un intento va a su resultado: lo que Playwright graba por su cuenta y lo que adjunta una prueba.

Actívalo en use, como siempre; el reporter sube lo que produce:

use: {
screenshot: 'only-on-failure',
video: 'retain-on-failure',
trace: 'retain-on-failure',
},
PlaywrightEl archivo en Probara
screenshottest-failed-1.png (y los demás que conserva Playwright)
videoEl vídeo .webm del intento
tracetrace.zip: ábrelo con npx playwright show-trace
Un intento fallido (Playwright 1.51 o posterior)error-context.md: la instantánea de la página en el fallo
Fallos de toHaveScreenshot()Las imágenes esperada, real y de diferencias

Cada intento tiene sus propios archivos, así que una prueba reintentada sube los archivos de cada intento, cada uno a su resultado.

La API de Playwright funciona tal cual, con un archivo o con un cuerpo:

tests/api.spec.ts
import { test } from '@playwright/test';
test('creates an order', async ({ page }, testInfo) => {
await testInfo.attach('order', {
body: JSON.stringify({ id: 1042, total: 25 }),
contentType: 'application/json',
});
await testInfo.attach('checkout', { body: await page.screenshot(), contentType: 'image/png' });
});

Los archivos toman el nombre del adjunto, con la extensión de su tipo de contenido:

order.json application/json
checkout.png image/png

probara.attach() hace lo mismo desde cualquier sitio donde se ejecute una prueba (un helper, un fixture, un page object), sin tener que pasar testInfo. Pásale un archivo en disco o un cuerpo, y espéralo con await:

tests/receipt.spec.ts
import { writeFile } from 'node:fs/promises';
import { test } from '@playwright/test';
import { probara } from '@probara/playwright-reporter';
test('prints the receipt', async () => {
const path = test.info().outputPath('receipt.txt');
await writeFile(path, 'Total: 25.00');
await probara.attach({ name: 'receipt.txt', path });
await probara.attach({ name: 'log', body: 'paid in 1.2 s', contentType: 'text/plain' });
});
receipt.txt text/plain
log.txt text/plain
CampoCon pathCon body
nameObligatorio: el nombre en ProbaraObligatorio: el nombre en Probara
pathEl archivo que adjuntar (Playwright lo copia)—
body—Un string, un Buffer o un Uint8Array
contentTypeOpcional: se deduce del nombre del archivoObligatorio, por ejemplo text/plain

Un cuerpo de tipo string se envía tal cual; pasa un Buffer para contenido binario. Un archivo que no se puede adjuntar (porque no existe, por ejemplo) es una advertencia [probara] en el stderr de la prueba, y la prueba continúa.

Un archivo adjuntado mientras se ejecuta un test.step (con testInfo.attach() o probara.attach()) va a ese paso, y Probara lo muestra bajo el paso, donde ocurrió:

tests/upload.spec.ts
import { test } from '@playwright/test';
import { probara } from '@probara/playwright-reporter';
test('uploads an avatar', async ({ page }) => {
await test.step('Choose the file', async () => {
await probara.attach({
name: 'avatar',
body: await page.screenshot(),
contentType: 'image/png',
});
});
});

Un archivo adjuntado dentro de un hook o de un fixture que no es un test.step va al test.step más cercano que lo rodea, o al resultado.

Un archivo conserva su propio nombre (test-failed-1.png, trace.zip). Playwright guarda lo que copia testInfo.attach() con un nombre con hash (receipt-<sha1>.txt), y un informe blob combinado guarda así todos los archivos; un archivo así toma el nombre de su adjunto, con la extensión del archivo cuando el nombre no la tiene: receipt.txt, avatar.png.

Con captureOutput: true (PROBARA_CAPTURE_OUTPUT=true), el stdout y el stderr de cada intento se adjuntan como stdout.log y stderr.log, cuando hay alguna salida:

reporter: [['@probara/playwright-reporter', { captureOutput: true }]],
tests/logs.spec.ts
import { test } from '@playwright/test';
test('prints what it does', async () => {
console.log('Opening the cart');
console.error('Slow response: 2.1 s');
});
stdout.log text/plain
stderr.log text/plain
LímiteQué pasa
32 MiB por archivoUn archivo más grande se omite con una advertencia
20 archivos por resultadoLos archivos a partir del 20 se omiten, con una sola advertencia
Imágenes de más de 10 MiB o de más de 8192 px de ancho o altoSe omiten con una advertencia (Probara convierte las imágenes a WebP)
Ejecutables y scriptsSe omiten: Probara rechaza sus tipos de contenido
Un archivo que falta, ilegible o vacíoSe omite con una advertencia
Un resultado que no registró nadaSus archivos no se suben

Las advertencias nombran el archivo, y el registro termina con cuántos archivos se adjuntaron, se omitieron y fallaron. uploadAttachments: false (PROBARA_UPLOAD_ATTACHMENTS=false) no sube ninguno. Cada resultado con archivos cuesta dos peticiones más contra el límite de tasa de la organización.

Los archivos se suben después de que su informe se registra, mientras la ejecución sigue abierta, y luego la ejecución se cierra. Conserva la carpeta de salida de Playwright (test-results/) hasta que el reporter termine: sube los archivos desde ahí.

PlaywrightQué cambia
1.51 o posteriorUn intento fallido sube además error-context.md
1.50 o posteriorLos archivos van al paso en el que se adjuntaron; test.step.skip() es un paso skipped
1.42 a 1.49Playwright no indica a qué paso pertenece un archivo: todos los archivos se quedan en el resultado; test.step.skip() no existe

Nada falla con una versión anterior de Playwright dentro del rango admitido: esos detalles simplemente no aparecen.

  • Falta un paso. Solo test.step crea pasos. Una función auxiliar que no está envuelta en test.step no muestra nada; tampoco las llamadas a expect.
  • Los pasos salen aplanados. Un paso que empieza sin await termina antes que sus hijos: espera cada test.step con await.
  • El caso no tiene pasos. Solo los títulos probara.step() declaran pasos de caso, y solo para un caso que crea el informe. Un caso existente conserva los suyos.
  • Falta un adjunto. Consulta la solución de problemas.

Siguiente: resultados y reintentos.