Ir al contenido

Migrar al reporter de Playwright

Esta página hace corresponder playwright-qase-reporter con el reporter de Probara opción por opción y llamada por llamada, muestra cómo pasar de probara import junit sin perder ningún caso y explica cómo se versiona el reporter.

Pasar de playwright-qase-reporter es sobre todo cuestión de renombrar: el registro del reporter, los ajustes y las llamadas qase.*.

  1. Cambia los paquetes:

    Ventana de terminal
    npm uninstall playwright-qase-reporter && npm i -D @probara/playwright-reporter
  2. En playwright.config, sustituye ['playwright-qase-reporter', {...}] por ['@probara/playwright-reporter', {...}], traduciendo las opciones (abajo). Borra qase.config.json: el reporter solo lee sus opciones y las variables PROBARA_*.

  3. Sustituye las variables QASE_* por las PROBARA_* en CI: como mínimo PROBARA_API_TOKEN (un token de aplicación de la tarjeta Playwright, consulta primeros pasos) y PROBARA_PROJECT.

  4. Sustituye import { qase } from 'playwright-qase-reporter' por import { probara } from '@probara/playwright-reporter', y traduce las llamadas (abajo). Los IDs de caso pasan a ser IDs visibles de Probara (SHOP-12), no números.

Antes:

playwright.config.ts
import { defineConfig } from '@playwright/test';
export default defineConfig({
reporter: [
['list'],
[
'playwright-qase-reporter',
{
mode: 'testops',
testops: {
project: 'SHOP',
run: { title: 'Nightly', complete: true, tags: ['nightly'] },
uploadAttachments: true,
},
captureLogs: true,
},
],
],
});

Después:

playwright.config.ts
import { defineConfig } from '@playwright/test';
export default defineConfig({
reporter: [
['list'],
[
'@probara/playwright-reporter',
{
projectId: 'SHOP',
run: { name: 'Nightly', tags: ['nightly'] },
captureOutput: true,
},
],
],
});
Opción de Qase (variable QASE_*)Opción de Probara (variable PROBARA_*)
mode: 'testops' (QASE_MODE)Activo siempre que haya un token y un proyecto
mode: 'off'enabled: false (PROBARA_ENABLED=false), o sin token
mode: 'report', fallbackresultsFile (PROBARA_RESULTS_FILE)
mode: 'testops_multi', testops_multi.*projectId junto con projects y run.ulids
debug (QASE_DEBUG)debug (PROBARA_DEBUG)
environment (QASE_ENVIRONMENT), un slugrun.environment (PROBARA_ENVIRONMENT), un nombre, que se crea si falta
rootSuite (QASE_ROOT_SUITE)suiteUlid (PROBARA_SUITE_ULID): una suite existente, por ULID
captureLogs (QASE_CAPTURE_LOGS)captureOutput (PROBARA_CAPTURE_OUTPUT)
statusMapping (QASE_STATUS_MAPPING)statusMapping (PROBARA_STATUS_MAPPING), sin invalid
logging.console, logging.fileEl registro va a stderr; la opción logger para código
testops.api.token (QASE_TESTOPS_API_TOKEN)PROBARA_API_TOKEN (apiToken para código)
testops.api.host (QASE_TESTOPS_API_HOST)baseUrl (PROBARA_BASE_URL), una URL completa
testops.api.timeout (segundos)timeoutMs (milisegundos)
testops.api.retries, testops.api.retryBackoffmaxRetries; la espera entre reintentos es fija
testops.project (QASE_TESTOPS_PROJECT)projectId (PROBARA_PROJECT)
testops.uploadAttachmentsuploadAttachments (PROBARA_UPLOAD_ATTACHMENTS)
testops.attachments.concurrency, .timeoutattachmentConcurrency; las subidas tienen al menos 120 s
testops.run.id (QASE_TESTOPS_RUN_ID)run.ulid (PROBARA_RUN_ULID)
testops.run.title, .description, .tagsrun.name, run.description, run.tags (PROBARA_RUN_*)
testops.run.completecloseRun (PROBARA_CLOSE_RUN); una ejecución creada se cierra por defecto
testops.plan.id (QASE_TESTOPS_PLAN_ID)run.plan (PROBARA_PLAN): el ID visible o el nombre del plan
testops.configurations.values (group=value)run.configurations (PROBARA_CONFIGURATIONS=Group=Name)
testops.statusFilter (QASE_TESTOPS_STATUS_FILTER)statusFilter (PROBARA_STATUS_FILTER)
testops.batch.sizechunkSize (de 1 a 500)
framework.browser.addAsParameterNada que configurar: el proyecto de Playwright se envía como parámetro project, no forma parte de la clave

Cada opción de Probara se describe en la referencia de configuración. Los ajustes de Qase sin equivalente están en lo que no se ha portado.

QaseProbara
test(qase(12, 'pays'), ...)test('SHOP-12 pays', ...), o una anotación
test(qase([12, 13], 'pays'), ...)test('pays', { annotation: { type: 'probara_case', description: 'SHOP-12, SHOP-13' } }, ...)
Anotación { type: 'QaseID', description: '12' }{ type: 'probara_case', description: 'SHOP-12' }
(Qase ID: 12) en un títuloSHOP-12 en un título
qase.id(12)probara.id('SHOP-12')
qase.title('...')probara.title('...')
qase.suite('Payments\tCards'), una anotación QaseSuiteprobara.suite(['Payments', 'Cards'])
qase.fields({ severity: 'critical' })probara.fields({ severity: 'critical' })
qase.tags('smoke')probara.tags('smoke')
qase.comment('...')probara.comment('...')
qase.ignore()probara.ignore()
qase.parameters({...}), qase.groupParameters({...})probara.parameters({...})
qase.attach({ paths: [a, b] })await probara.attach({ name, path }), una vez por archivo
qase.attach({ name, content, contentType })await probara.attach({ name, body, contentType })
qase.step('Pay', 'Paid', 'card=visa')probara.step('Pay', 'Paid', 'card=visa')
qase.projects({ WEB: [3] }), qase.projectsTitle(...), una anotación QaseProjectsWEB-3 como ID de caso, con projects: ['WEB']

Antes:

tests/checkout.spec.ts
import { test } from '@playwright/test';
import { qase } from 'playwright-qase-reporter';
test(qase(12, 'pays with a card'), async () => {
qase.fields({ severity: 'critical' }).tags('smoke');
await test.step(qase.step('Pay', 'The order is paid'), async () => {});
qase.attach({ name: 'order.json', content: '{"id":1042}', contentType: 'application/json' });
});

Después:

tests/checkout.spec.ts
import { test } from '@playwright/test';
import { probara } from '@probara/playwright-reporter';
test('SHOP-12 pays with a card', async () => {
probara.fields({ severity: 'critical' }).tags('smoke');
await test.step(probara.step('Pay', 'The order is paid'), async () => {});
await probara.attach({
name: 'order.json',
body: '{"id":1042}',
contentType: 'application/json',
});
});

Lo que recibe Probara:

[
{
"caseDisplayId": "SHOP-12",
"automationKey": "checkout.spec.ts > pays with a card",
"steps": [{ "action": "Pay", "expected": "The order is paid" }],
"case": { "tags": ["smoke"], "fields": { "severity": "critical" } }
}
]
TemaQaseProbara
PrecedenciaSu código hace que las variables ganen a qase.config.json, que gana a las opciones del reporter (su documentación dice lo contrario)Las opciones de playwright.config, después las variables PROBARA_*, después los valores por defecto: lo que dice la configuración es lo que se ejecuta
Archivo de configuraciónqase.config.json o .qasercNinguno: un archivo de configuración con un token podría subirse al repositorio. Las opciones viven en playwright.config
IDs de casoNúmeros, con un mapeo por proyectoIDs visibles (SHOP-12): el ID del Proyecto dirige cada ID a su proyecto
test.fail()Se ignora: un fallo esperado se envía como fallido (o inválido), y un acierto inesperado como pasadoEl veredicto de Playwright: un fallo esperado pasa, un acierto inesperado falla (estados)
Estadosinvalid para un fallo cuyo error no parece una aserción (una suposición a partir del mensaje)passed, failed, skipped; blocked solo mediante statusMapping. Nada se deduce del texto del error
Intentos interrumpidosfailed (su documentación dice skipped)failed
Campos del casoSe envían con cada resultadoSolo cuando el informe crea el caso: un caso existente conserva lo que escribieron las personas
Llamadas a fields()La última llamada sustituye a las demásSe combinan por nombre
Cierre de la ejecuciónSolo con run.complete: trueUna ejecución que crea el reporter se cierra al final; una reutilizada queda abierta
ShardsCada shard crea su propia ejecución salvo que reciba un ID de ejecuciónmerge-reports, o probara run create y run close (shards)
Cuando el envío fallafallback a un informe localUn archivo de resultados, que probara import results envía después a las mismas ejecuciones
Strings en attach()Un string que parece base64 se decodificaUn string se envía tal cual; pasa un Buffer para contenido binario
Error de un resultadoEl texto del contexto de error en un campo propioTodos los errores en las notas; error-context.md como archivo
Intentos inestablesframework.markAsFlaky marca un reintento que pasaCada intento es un resultado; sin marca (reintentos)
Funcionalidad de QasePor qué
Enlace público al informe (showPublicReportLink)Un enlace público a los resultados es una decisión de compartir que corresponde a la aplicación de Probara, no algo que deba activar un job de CI
Defectos automáticos (testops.defect)Registrar un defecto por cada fallo inunda la lista de defectos; informa de los defectos desde el resultado en Probara
Perfilador de red (profilers: ['network'])Registra como pasos las llamadas HTTP del proceso de pruebas, que son ruido en pruebas de navegador; adjunta lo importante con probara.attach()
Enlace de Jira en las ejecuciones (run.externalLink)Probara vincula las incidencias de Jira a los casos y a los defectos, donde vive la trazabilidad
Un campo de error aparte (error_context)Los errores van en las notas, y el contexto de error se adjunta como archivo, así que nada se recorta por el tamaño de un campo
qase.mute()Qase lo documenta, pero no existe en su reporter
Crear configuraciones (createIfNotExists)Las configuraciones forman parte de la planificación de un proyecto; una desconocida se rechaza, así que una errata nunca crea una nueva
framework.markAsFlakyCada intento es un resultado: el historial muestra la inestabilidad sin necesidad de una marca
Registro en un archivo (logging.file)El registro va a stderr, donde lo conserva el CI; redirige stderr para guardarlo en un archivo

El reporter construye las mismas claves de automatización que la CLI de Probara asigna al reporter JUnit de Playwright (--reporter=junit), y lee los mismos vínculos: las anotaciones probara_case (que el reporter JUnit escribe como propiedades) y los IDs de caso en los títulos. Un proyecto que importaba el JUnit XML de Playwright con probara import junit puede pasarse al reporter y conservar cada caso:

  1. Mantén rootDir (o testDir) como estaba: el reporter JUnit escribe las rutas de los archivos de forma relativa a él.
  2. Sustituye el paso de importación de JUnit por el reporter en playwright.config, y mantén PROBARA_API_TOKEN y PROBARA_PROJECT en el entorno del paso de pruebas. Guarda ahí un token de aplicación de la tarjeta Playwright, para que las nuevas ejecuciones muestren la aplicación Playwright.
  3. Revisa las claves antes de cambiar: probara import junit junit.xml --dry-run imprime la clave de cada prueba, y un archivo de resultados escrito por el reporter con el envío desactivado imprime las suyas del mismo modo (comprobar qué se enviaría).

Lo que el reporter envía además de lo que enviaba la importación de JUnit: cada intento como resultado propio, los pasos, los adjuntos de los pasos, los metadatos y los archivos que conserva Playwright (vídeos, trazas).

@probara/playwright-reporter sigue el versionado semántico. Lee el changelog (en inglés) antes de actualizar: cada cambio que requiere una acción por tu parte aparece ahí en primer lugar.

  • 0.x (ahora): el reporter es joven. Una versión minor (0.2.0) puede cambiar opciones, líneas del registro o valores por defecto; una versión patch (0.1.1) solo corrige errores. Fija la versión en package.json (o conserva el lockfile) y actualiza cuando lo decidas.
  • 1.0 y posteriores: cambios incompatibles solo en una versión major.
  • El reporter depende de @probara/core de la misma línea de versiones; instala solo el reporter y deja que traiga su core.

Cualquiera de estos requiere una versión major a partir de 1.0, y una minor antes:

  • Una opción o una variable PROBARA_* eliminada o renombrada, o con un significado distinto.
  • Un valor por defecto que cambia (el cierre de ejecuciones, la creación de casos que faltan, lo que se adjunta).
  • Un helper probara.* eliminado, o con un comportamiento distinto.
  • Un estado distinto para el mismo intento.
  • Cualquier cambio en la clave de automatización que recibe una prueba. Una clave distinta desvincula la prueba de su caso: la siguiente ejecución crea uno nuevo.
  • Dejar de admitir una versión de Playwright o de Node.js que sigue teniendo soporte oficial.

Añadir una opción, un helper, una línea de registro o un archivo que se sube no es incompatible. Las líneas de stderr son para personas: no las analices con código.

El algoritmo es la clave de automatización v1, congelada en @probara/core y fijada con vectores de referencia: ninguna versión del reporter la cambia. Lo que añade el reporter es cómo una prueba de Playwright se convierte en las partes de la clave (el archivo relativo a rootDir, los describe y el título, el proyecto), igual que probara import junit lee el JUnit XML de Playwright (claves de automatización). Esa correspondencia también forma parte del contrato: una versión que cambie la clave de una prueba es un cambio incompatible, y el changelog lo indica como tal.

Para revisar una actualización, compara lo que enviarían las dos versiones: ejecuta la suite con el envío desactivado una vez por versión, cada una con su propio archivo de resultados (PROBARA_RESULTS_FILE=before.json y después after.json, sin que existan antes), y compara las dos simulaciones (comprobar qué se enviaría). Cada clave que cambie es una prueba que recibiría un caso nuevo.

RequiereCompatible
@playwright/test1.42 y posteriores (el rango de la dependencia peer): probado en 1.42 y en la última
Node.js22.12 y posteriores (el campo engines)

Algunas funciones dependen de la versión de Playwright: los archivos de los pasos y los pasos omitidos necesitan 1.50, y el contexto de error de un intento fallido necesita 1.51 (versiones de Playwright). Nada falla con una versión anterior de Playwright dentro del rango: esos detalles simplemente no aparecen.

  • 0.1.0 (2026-09-30) es la primera versión, y la primera publicada en npm: no hay nada desde lo que migrar.

Siguiente: primeros pasos, o la referencia de configuración.