Migrar al reporter de Cypress
Vengas de donde vengas, el reporter son tres registros: el reporter de la configuración de
Cypress, su plugin en setupNodeEvents y su archivo de soporte.
const { defineConfig } = require('cypress');const { probaraNodeEvents } = require('@probara/cypress-reporter/setup');
module.exports = defineConfig({ e2e: { reporter: '@probara/cypress-reporter', reporterOptions: { projectId: 'SHOP' }, setupNodeEvents(on, config) { return probaraNodeEvents(on, config); }, },});import '@probara/cypress-reporter/support';Si setupNodeEvents ya registra otros plugins (como el de la herramienta que dejas), consulta
con otros plugins.
| Vienes de | Ve a |
|---|---|
El reporter junit de Cypress o cypress-junit, con probara import junit | La importación JUnit |
| El reporter de Qase para Cypress | Qase |
allure-cypress | Allure Cypress |
JUnit XML y trcli parse_junit | TestRail |
Desde la importación JUnit
Sección titulada «Desde la importación JUnit»Si tu pipeline escribe JUnit XML con el reporter junit integrado en Cypress o con
cypress-junit, y lo envía con probara import junit,
el reporter puede sustituir ambos pasos sin desvincular ni un solo caso: da a cada prueba la
clave de automatización que le da la importación.
// cypress.config.js, beforemodule.exports = defineConfig({ e2e: { reporter: 'junit', // or 'cypress-junit' reporterOptions: { mochaFile: 'reports/cypress-[hash].xml', includePending: true }, },});- Sustituye el reporter JUnit por este, y registra su plugin y su archivo de soporte (arriba).
Cypress acepta un solo
reporter: para conservar el XML durante un tiempo, declara ambos encypress-multi-reporters. - Comprueba las claves de ambos sobre las mismas specs: tienen que ser iguales.
- En CI, quita el paso de importación, y pasa
PROBARA_API_TOKENal paso de pruebas.
| El informe JUnit | Ajuste del reporter |
|---|---|
Escrito con las opciones por defecto, con la spec en el file de su suite raíz | Nada: keyIncludesFile: true es el valor por defecto |
Escrito sin ese atributo file | keyIncludesFile: false (PROBARA_KEY_INCLUDES_FILE) |
Ambos caminos leen las mismas dos partes de una prueba: la ruta de la spec relativa a la raíz del
proyecto, y un solo segmento de título, los títulos de sus describe y el de su it unidos por
espacios, sin los IDs de caso. Ejecuta la importación desde la raíz del proyecto (o pasa
--root-dir): la importación expresa la ruta de la spec respecto al directorio en el que se
ejecuta, y el reporter respecto al projectRoot de Cypress.
Comprueba las claves antes de cambiar
Sección titulada «Comprueba las claves antes de cambiar»Ejecuta la batería una vez con el reporter JUnit y otra con el archivo de resultados del reporter, con el envío desactivado, y compara las pruebas en seco de ambos: cada una imprime una línea por resultado, con su estado, su caso y su clave.
npx cypress run # with the JUnit reporternpx --yes @probara/cli@0.3 import junit 'reports/cypress-*.xml' --dry-run > junit.txtPROBARA_ENABLED=false PROBARA_PROJECT=SHOP PROBARA_RESULTS_FILE=probara-results.json npx cypress run # with this reporternpx --yes @probara/cli@0.3 import results 'probara-results*.json' --dry-run > reporter.txt$ npx --yes @probara/cli@0.3 import results 'probara-results*.json' --dry-runpassed SHOP-12 cypress/e2e/cart.cy.js > Cart adds an itemUna línea cuya clave cambió es una prueba que recibiría un caso nuevo; las pruebas reintentadas y las que un hook fallido impidió ejecutar tienen más líneas del lado del reporter (qué cambia). Borra después el XML y el archivo de resultados.
La CLI lee el JUnit XML de Cypress como su dialecto cypress-junit desde la versión 0.3.
Reconoce un informe por sus señas: una raíz <testsuites> llamada Mocha Tests, exactamente un
testsuite con un file que es una spec de Cypress (cypress/ en su ruta, o un nombre .cy.*), y
testcases cuyo classname es el final de su name. Un informe que renombró la raíz
(testsuitesTitle), o specs fuera de cypress/ sin nombre .cy.*, se lee en cambio como
generic: pasa --dialect cypress-junit a la importación.
Antes, dos pasos: Cypress escribe el XML, y la CLI lo envía.
- name: Run Cypress tests run: npx cypress run- name: Send the results if: ${{ !cancelled() }} run: npx --yes @probara/cli@0.3 import junit 'reports/cypress-*.xml' env: PROBARA_API_TOKEN: ${{ secrets.PROBARA_API_TOKEN }} PROBARA_PROJECT: SHOPDespués, un paso: el reporter, registrado en la configuración de Cypress, envía cada resultado cuando termina la ejecución.
- name: Run Cypress tests run: npx cypress run env: PROBARA_API_TOKEN: ${{ secrets.PROBARA_API_TOKEN }} PROBARA_PROJECT: SHOPQué cambia respecto a la importación JUnit
Sección titulada «Qué cambia respecto a la importación JUnit»| Cypress | probara import junit | El reporter |
|---|---|---|
| Una prueba que falla y pasa en un reintento | Un resultado: el que pasó | Dos resultados de un caso: el intento fallido y después el que pasó |
| Una prueba que falla en todos los intentos | Un resultado: el último fallo | Un resultado por intento |
| Un hook que falla en todos los intentos | Solo el fallo del hook | El intento reintentado de la prueba, y el fallo del hook que nombra Cypress |
| Las pruebas que ese hook impidió ejecutar | Nada: no dejaron ningún testcase | Un resultado omitido cada una |
| Suite de un caso creado | Solo la spec | La spec y los bloques describe de la prueba |
El estado, el error en las notas, la duración y la hora de inicio son iguales. El reporter añade dos
parámetros que el JUnit no tiene dónde poner: browser y, desde el segundo intento, attempt. La
suite solo cambia dónde va un caso que crea el informe: un caso existente nunca se mueve.
Lo que ganas: cada intento de una prueba reintentada; la captura de cada intento fallido, y el vídeo
con attachVideos; pasos anidados; archivos y salida de consola; enlaces e incidencias; los campos
de los casos nuevos; la selección de pruebas; y los resultados fallidos asignados a las personas que
indiques.
Desde Qase
Sección titulada «Desde Qase»Pasar del reporter de Qase para Cypress es sobre todo cambiar nombres: ambos se registran como un
reporter, un hook de setupNodeEvents y un archivo de soporte, y sus helpers se corresponden uno a
uno. El único cambio que toca tus specs es la sintaxis del ID de caso.
Vincular por ID de caso
Sección titulada «Vincular por ID de caso»// with Qaseit('(Qase ID: 12) adds an item', () => { cy.get('.add').click();});
// with Probarait('SHOP-12 adds an item', () => { cy.get('.add').click();});(Qase ID: 12) no es un ID de Probara y no vincula nada: se queda en el título y en la clave, y la
prueba recibe un caso nuevo. No hay ninguna opción que lea la sintaxis de Qase. Cambia primero los
IDs, o llama a probara.id('SHOP-12') sin tocar el título
(vincular).
Los nombres, uno junto a otro
Sección titulada «Los nombres, uno junto a otro»| En una batería con Qase | En una batería con Probara | Qué cambia |
|---|---|---|
(Qase ID: 12) en el título de un it o describe | SHOP-12 en el título, o probara.id('SHOP-12') | La sintaxis del ID |
qase.title() / qase.suite() | probara.title() / probara.suite() | Lo mismo, para el caso que crea el informe |
qase.fields | probara.fields({ ... }) | Solo tiene efecto cuando el informe crea un caso |
qase.comment | probara.comment(text) | Se escribe al principio de las notas del resultado, antes del error |
qase.ignore | probara.ignore() | Lo mismo |
qase.parameters / groupParameters | probara.parameters({ ... }) | Una sola llamada para ambos; el navegador se añade solo |
qase.step(title, params) | probara.step(title, body?, { expected, data }) | Con cuerpo o sin él; el anidamiento sigue el orden de las llamadas |
qase.attach({ paths | content }) | probara.attach({ name, path | body }) | El nombre es obligatorio; un archivo que falta se omite con una advertencia |
| Un proyecto por prefijo de ID de caso | projects y el prefijo del ID de caso | Varios proyectos |
QASE_REPORT | PROBARA_API_TOKEN y PROBARA_PROJECT | El envío se activa cuando ambos están definidos; se desactiva con enabled: false |
QASE_RUN_ID | PROBARA_RUN_ULID (run.ulid) | Reportar en una ejecución que ya existe |
| El modo report y su carpeta de resultados | resultsFile y probara import results | Un archivo JSON con lo que no se pudo enviar, enviado más tarde |
Capturas buscadas en screenshotsFolder | Nada que configurar | Adjuntas al intento exacto (attachScreenshots, activado por defecto) |
El vídeo buscado en videosFolder | video: true y attachVideos | Desactivado por defecto: una subida por resultado fallido |
Ambos reporters envían un resultado por intento, reportan it.skip como omitida, y reportan como
omitidas las pruebas que un beforeEach fallido impidió ejecutar. Probara añade el parámetro
attempt desde el segundo intento.
Lo que no se porta de Qase
Sección titulada «Lo que no se porta de Qase»| Función de Qase | Por qué no |
|---|---|
El perfilador de red (el registrador de cy.intercept) | Una tarea por petición: más ruido y coste que valor |
qase.cucumberSteps | Los pasos de Cucumber son cosa de un preprocesador BDD |
| Un perfil de reintentos (qué intentos conservar) | Cada intento es un resultado; statusMapping y statusFilter son las únicas reglas que cambian o descartan uno |
Hooks propios de la ejecución (beforeRunHook, afterRunHook) | El plugin crea la ejecución, la envía y la cierra cuando termina la ejecución; closeRun decide si se cierra |
Desde Allure Cypress
Sección titulada «Desde Allure Cypress»El plugin de Allure se registra en setupNodeEvents y publica su API en el archivo de soporte, como
este reporter: sustituye ambos registros y cambia el nombre de las llamadas.
| Allure Cypress | Probara | Qué cambia |
|---|---|---|
allure.step(name, body) | probara.step(title, body?, { expected, data }) | expected y data son el resultado esperado y los datos del paso del caso |
stepsFromCommands (cada comando, un paso) | Nada: los comandos no son pasos | Nombra los pasos con probara.step(); Probara guarda 200 pasos por resultado |
allure.attachment(name, content, type) | probara.attach({ name, body, contentType }) | El plugin lee un path desde la raíz del proyecto |
allure.link(url, name) / allure.issue(id) | probara.link(url, name?) / probara.issue(id) | Una incidencia se convierte en enlace mediante issueUrlTemplate |
allure.tms | probara.link(url, name?) | Un enlace normal |
displayName, description, severity | probara.title(), probara.fields({ ... }) | Campos del caso que crea el informe |
| Etiquetas (labels y tags) | probara.tags('smoke', 'cart') | Etiquetas del caso creado |
allure.parameter(name, value) | probara.parameters({ name: value }) | El navegador se añade solo |
historyId | Nada: la clave es la ruta de la spec y el título completo | Una clave propia renombraría cada caso que conoce la importación |
| El vídeo de una spec | video: true y attachVideos | Desactivado por defecto: una subida por resultado fallido |
No se portan: un responsable del caso (Probara no tiene ese campo), los parámetros enmascarados (se envían todos los parámetros), y las categorías, los problemas conocidos y los enlaces de defectos de Allure.
Desde TestRail
Sección titulada «Desde TestRail»trcli es un comando, no un reporter: lee el JUnit XML de la ejecución y lo sube después de las
pruebas. El reporter sustituye tanto el XML como la subida.
| trcli | Probara |
|---|---|
--user / --password / --project | PROBARA_API_TOKEN (la tarjeta Cypress) y projectId |
--add-run, --close-run | La ejecución se crea y se cierra sola; run.ulid reutiliza una |
--milestone, --plan, --configuration | run.milestone, run.plan, run.configurations |
--refs | Nada: una ejecución de Probara no tiene campos de referencia propios; acepta run.tags |
parse_junit | Nada: los resultados se envían cuando termina la ejecución |
-a, --assign | assignFailedTo |
--case-fields | probara.fields({ ... }) para el caso que crea el informe |
--case-matcher | Nada: la clave de automatización es la ruta de la spec y el título completo |
automation_id, un C123 en el título | Un ID de caso en el título (SHOP-1), o probara.id('SHOP-1') |
--run-id | PROBARA_RUN_ULID |
--result-fields | No se porta: Probara no tiene campos de resultado |
--update-existing-cases, --update-strategy | No se porta: un informe nunca cambia un caso; cámbialo en Probara, donde se puede revisar |
Actualizar el reporter
Sección titulada «Actualizar el reporter»@probara/cypress-reporter sigue el versionado semántico. Lee el
changelog
antes de actualizar: cada cambio que requiere una acción por tu parte aparece ahí primero.
- 0.x (ahora): el reporter es joven. Una versión menor (
0.2.0) puede cambiar opciones, líneas del registro o valores por defecto; una versión de parche (0.1.1) solo corrige errores. Fija la versión enpackage.json(o conserva el lockfile) y actualiza a propósito. - 1.0 y posteriores: cambios incompatibles solo en una versión mayor.
@probara/cypress-reporterdepende 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 necesita una versión mayor a partir de la 1.0, y una menor antes:
- Una opción o una variable
PROBARA_*eliminada o renombrada, o con un significado distinto. - Un valor por defecto cambiado (el cierre de ejecuciones, la creación de casos que faltan,
keyIncludesFile, lo que se adjunta). - Un helper
probara.*, el plugin (@probara/cypress-reporter/setup) o el archivo de soporte (@probara/cypress-reporter/support) eliminado, o con un comportamiento distinto. - Un cambio del estado con el que se envía un intento, para el mismo intento.
- Cualquier cambio en la clave de automatización de una prueba, con
keyIncludesFileactivado o no. Una clave distinta desvincula la prueba de su caso: la siguiente ejecución crea uno nuevo. - Dejar de admitir una versión de Cypress o de Node.js que sigue teniendo soporte oficial.
Añadir una opción, un helper, una línea de registro o un archivo subido no es incompatible. Las
líneas [probara] 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 de la clave es la
clave de automatización v1,
congelada en @probara/core y fijada por vectores de referencia: ninguna versión del reporter la
cambia. Lo que añade el reporter es cómo una prueba de Cypress se convierte en las partes de la
clave, del mismo modo en que probara import junit lee el informe del reporter junit de Cypress o
de cypress-junit:
- el archivo de la spec relativo al
projectRootde Cypress, cuandokeyIncludesFileestá activado, como el atributofilede la suite raíz del informe; - el título completo, los títulos de los
describey el delitunidos por un espacio, como un solo segmento, sin los IDs de caso.
Esa correspondencia también forma parte del contrato: una versión que cambia la clave de una prueba es un cambio incompatible, señalado como tal en el changelog. Para comprobar una actualización, compara lo que enviarían ambas versiones, cada una con su propio archivo de resultados (comprobar qué se enviaría). Cada clave que cambie es una prueba que recibiría un caso nuevo.
Versiones de Cypress y de Node.js
Sección titulada «Versiones de Cypress y de Node.js»| Necesita | Compatible |
|---|---|
| Cypress | 15.10.0 y posteriores (el rango de peer); probado en 16.1.1 |
| Node.js | 22.12 y posteriores (el campo engines), para el Node.js que arranca cypress |
Cypress 15.10.0 es la primera versión con Cypress.expose(), que el plugin usa para entregar sus
ajustes al navegador: en un Cypress anterior, los helpers probara.* no tendrían nada que leer. El
plugin se ejecuta en el Node.js que arranca cypress; el reporter, en el Node.js que trae Cypress.
Cypress 15 todavía funciona con Node.js 20, y este reporter no: un proyecto con Cypress 15 y
Node.js 20 tiene que actualizar antes Node.js. 0.1.0 es la primera versión: todavía no hay nada
desde lo que migrar.
Relacionado: Primeros pasos · Vincular · CLI · Fuente: migrating-from-junit.md, migrating-from-qase.md, coming-from-other-tools.md, upgrade.md