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.
Desde Qase
Sección titulada «Desde Qase»Pasar de playwright-qase-reporter es sobre todo cuestión de renombrar: el registro del reporter,
los ajustes y las llamadas qase.*.
-
Cambia los paquetes:
Ventana de terminal npm uninstall playwright-qase-reporter && npm i -D @probara/playwright-reporter -
En
playwright.config, sustituye['playwright-qase-reporter', {...}]por['@probara/playwright-reporter', {...}], traduciendo las opciones (abajo). Borraqase.config.json: el reporter solo lee sus opciones y las variablesPROBARA_*. -
Sustituye las variables
QASE_*por lasPROBARA_*en CI: como mínimoPROBARA_API_TOKEN(un token de aplicación de la tarjeta Playwright, consulta primeros pasos) yPROBARA_PROJECT. -
Sustituye
import { qase } from 'playwright-qase-reporter'porimport { 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:
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:
import { defineConfig } from '@playwright/test';
export default defineConfig({ reporter: [ ['list'], [ '@probara/playwright-reporter', { projectId: 'SHOP', run: { name: 'Nightly', tags: ['nightly'] }, captureOutput: true, }, ], ],});Opciones y variables
Sección titulada «Opciones y variables»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', fallback | resultsFile (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 slug | run.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.file | El 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.retryBackoff | maxRetries; la espera entre reintentos es fija |
testops.project (QASE_TESTOPS_PROJECT) | projectId (PROBARA_PROJECT) |
testops.uploadAttachments | uploadAttachments (PROBARA_UPLOAD_ATTACHMENTS) |
testops.attachments.concurrency, .timeout | attachmentConcurrency; las subidas tienen al menos 120 s |
testops.run.id (QASE_TESTOPS_RUN_ID) | run.ulid (PROBARA_RUN_ULID) |
testops.run.title, .description, .tags | run.name, run.description, run.tags (PROBARA_RUN_*) |
testops.run.complete | closeRun (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.size | chunkSize (de 1 a 500) |
framework.browser.addAsParameter | Nada 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.
Las llamadas qase.*
Sección titulada «Las llamadas qase.*»| Qase | Probara |
|---|---|
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ítulo | SHOP-12 en un título |
qase.id(12) | probara.id('SHOP-12') |
qase.title('...') | probara.title('...') |
qase.suite('Payments\tCards'), una anotación QaseSuite | probara.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 QaseProjects | WEB-3 como ID de caso, con projects: ['WEB'] |
Antes:
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:
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" } } }]Qué cambia y por qué
Sección titulada «Qué cambia y por qué»| Tema | Qase | Probara |
|---|---|---|
| Precedencia | Su 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ón | qase.config.json o .qaserc | Ninguno: un archivo de configuración con un token podría subirse al repositorio. Las opciones viven en playwright.config |
| IDs de caso | Números, con un mapeo por proyecto | IDs 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 pasado | El veredicto de Playwright: un fallo esperado pasa, un acierto inesperado falla (estados) |
| Estados | invalid 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 interrumpidos | failed (su documentación dice skipped) | failed |
| Campos del caso | Se envían con cada resultado | Solo 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ás | Se combinan por nombre |
| Cierre de la ejecución | Solo con run.complete: true | Una ejecución que crea el reporter se cierra al final; una reutilizada queda abierta |
| Shards | Cada shard crea su propia ejecución salvo que reciba un ID de ejecución | merge-reports, o probara run create y run close (shards) |
| Cuando el envío falla | fallback a un informe local | Un archivo de resultados, que probara import results envía después a las mismas ejecuciones |
Strings en attach() | Un string que parece base64 se decodifica | Un string se envía tal cual; pasa un Buffer para contenido binario |
| Error de un resultado | El texto del contexto de error en un campo propio | Todos los errores en las notas; error-context.md como archivo |
| Intentos inestables | framework.markAsFlaky marca un reintento que pasa | Cada intento es un resultado; sin marca (reintentos) |
Lo que no se ha portado
Sección titulada «Lo que no se ha portado»| Funcionalidad de Qase | Por 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.markAsFlaky | Cada 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 |
Desde probara import junit
Sección titulada «Desde probara import junit»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:
- Mantén
rootDir(otestDir) como estaba: el reporter JUnit escribe las rutas de los archivos de forma relativa a él. - Sustituye el paso de importación de JUnit por el reporter en
playwright.config, y manténPROBARA_API_TOKENyPROBARA_PROJECTen 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. - Revisa las claves antes de cambiar:
probara import junit junit.xml --dry-runimprime 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).
Actualizar
Sección titulada «Actualizar»@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.
Política de versiones
Sección titulada «Política de versiones»- 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 enpackage.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/corede la misma línea de versiones; instala solo el reporter y deja que traiga su core.
Qué es un cambio incompatible
Sección titulada «Qué es un cambio incompatible»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 contrato de la clave de automatización
Sección titulada «El contrato de la clave de automatización»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.
Versiones compatibles
Sección titulada «Versiones compatibles»| Requiere | Compatible |
|---|---|
@playwright/test | 1.42 y posteriores (el rango de la dependencia peer): probado en 1.42 y en la última |
| Node.js | 22.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.
Notas de versión
Sección titulada «Notas de versión»- 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.