Migrar al reporter de Vitest
Vengas de donde vengas, el reporter es una entrada en reporters. No va nada en setupFiles ni en
runner: el reporter añade su propio archivo de setup y su runner a cada proyecto de Vitest, en
Node y en modo navegador.
// vitest.config.mtsimport { defineConfig } from 'vitest/config';
export default defineConfig({ test: { reporters: ['default', ['@probara/vitest-reporter', { projectId: 'SHOP' }]], },});El reporter envía lo que envían las integraciones con Vitest de Qase, Allure, ReportPortal y TestRail, siempre que Probara tenga un lugar para ello: vínculos con casos, el título, la suite, los campos, las etiquetas y los pasos de un caso nuevo, parámetros, comentarios, pasos anidados, archivos, enlaces, y el nombre, el plan, el entorno y las configuraciones de la ejecución. Además envía cada intento de una prueba reintentada o repetida, cosa que ninguna de ellas hace, y mantiene una sola ejecución para toda una sesión watch. Lo que no porta está en lo que el reporter no admite, cada cosa con su motivo.
| Vienes de | Ve a |
|---|---|
La salida JUnit de Vitest y probara import junit | La importación JUnit |
vitest-qase-reporter | Qase |
allure-vitest | Allure |
@reportportal/agent-js-vitest | ReportPortal |
La salida JUnit de Vitest y trcli parse_junit | TestRail |
Desde la importación JUnit
Sección titulada «Desde la importación JUnit»Si tu pipeline escribe la salida JUnit de Vitest y la envía con probara import junit, el reporter
puede sustituir ambos pasos sin desvincular un solo caso: da a cada prueba la clave de
automatización y el caso que le da la importación, en Vitest 3, 4 y 5. Después, cada prueba envía
lo que el XML no puede contener: cada intento, los pasos, los archivos, los parámetros y las
llamadas probara.*. El reporter es el camino recomendado; conserva la importación para un job que
solo tiene el XML.
- Añade el reporter a la configuración de Vitest
(primeros pasos).
No hay nada más que definir: la salida JUnit de Vitest siempre nombra el archivo de prueba, igual
que las claves por defecto del reporter (
keyIncludesFile: true). - Comprueba las claves de ambos sobre las mismas pruebas: deben ser iguales.
- En CI, quita
--reporter=junity el paso de importación, y pasaPROBARA_API_TOKENal paso de pruebas (en CI).
| Salida JUnit de Vitest | Ajuste del reporter |
|---|---|
--reporter=junit, con o sin addFileAttribute: true | Nada: keyIncludesFile: true es el valor por defecto |
Escrita con otro ancestorSeparator (Vitest 5) | Claves distintas: vincula las pruebas por IDs de caso (vincular) |
Ejecuta vitest desde la misma raíz que antes: el archivo de cada clave es relativo a ella, en los
dos caminos. keyIncludesFile: false no tiene equivalente en JUnit: da las claves de casos creados
a mano o por otra herramienta, sin el archivo
(sin el archivo).
Comprueba las claves antes de cambiar
Sección titulada «Comprueba las claves antes de cambiar»Ejecuta la batería una vez con la salida JUnit de Vitest y otra con el archivo de resultados del reporter, con el envío desactivado, y compara las simulaciones de ambos: cada una imprime una línea por resultado, con su estado, su caso y su clave. No hace falta token. Para este archivo de prueba:
import { describe, expect, test } from 'vitest';
describe('refund', () => { test('SHOP-12 refunds an order', () => { expect(25 - 25).toBe(0); });
test('keeps the receipt', () => { expect('receipt').toHaveLength(7); });
test.todo('refunds a gift card');});$ npx vitest run --reporter=junit --outputFile=reports/vitest.xml$ PROBARA_PROJECT=SHOP npx @probara/cli import junit reports/vitest.xml --dry-runpassed SHOP-12 tests/refund.test.ts > refund > refunds an orderpassed - tests/refund.test.ts > refund > keeps the receiptskipped - tests/refund.test.ts > refund > refunds a gift cardTotal: 3 results from 1 file (2 passed, 0 failed, 1 skipped, 0 blocked)$ PROBARA_ENABLED=false PROBARA_PROJECT=SHOP PROBARA_RESULTS_FILE=probara-results.json npx vitest run[probara] Wrote 3 results to /work/shop/probara-results.json: send them with probara import results /work/shop/probara-results.json$ npx @probara/cli import results probara-results.json --dry-runpassed SHOP-12 tests/refund.test.ts > refund > refunds an orderpassed - tests/refund.test.ts > refund > keeps the receiptskipped - tests/refund.test.ts > refund > refunds a gift cardTotal: 3 results from 1 file (2 passed, 0 failed, 1 skipped, 0 blocked)Las líneas son iguales: las mismas claves, los mismos casos y los mismos estados. --reporter=junit
sustituye los reporters de la configuración en esa ejecución, así que entonces el reporter no envía
nada. En una batería real, escribe cada simulación en un archivo y compáralos con diff: una línea
cuya clave cambió es una prueba que recibiría un caso nuevo
(comprobar qué se enviaría).
Elimina reports/ y el archivo de resultados al terminar.
Antes, dos pasos: Vitest escribe el informe, y la CLI lo envía.
- name: Run the tests run: npx vitest run --reporter=junit --outputFile=reports/vitest.xml- name: Send the results if: ${{ !cancelled() }} run: npx @probara/cli import junit reports/vitest.xml env: PROBARA_API_TOKEN: ${{ secrets.PROBARA_API_TOKEN }} PROBARA_PROJECT: SHOPDespués, un solo paso: el reporter, registrado en la configuración de Vitest, envía cada resultado cuando termina la ejecución.
- name: Run the tests run: npx vitest run env: PROBARA_API_TOKEN: ${{ secrets.PROBARA_API_TOKEN }} PROBARA_PROJECT: SHOPQuita --reporter=junit del comando: sustituye los reporters de la configuración, incluido el del
reporter. Si otra herramienta sigue leyendo el XML (un resumen de pruebas del CI), lista en cambio
junit junto al reporter:
reporters: ['default', 'junit', '@probara/vitest-reporter'],outputFile: { junit: 'reports/vitest.xml' },La ejecución recibe el nombre, el origen y el cierre que le daba la importación (la ejecución).
Qué cambia respecto a la importación JUnit
Sección titulada «Qué cambia respecto a la importación JUnit»Las claves se mantienen; lo que envía cada prueba crece, y algunos resultados son más exactos:
| Tema | probara import junit sobre la salida JUnit de Vitest | El reporter |
|---|---|---|
Reintentos (retry) | Un resultado por prueba: un aprobado en un reintento es un aprobado sin más; una prueba que falla en todos los intentos conserva su primer fallo | Cada intento, en orden, cada uno con sus propios errores; el caso de la ejecución conserva el último resultado (reintentos) |
Repeticiones (repeats) | Un resultado por prueba | Cada ejecución (repeticiones) |
test.todo | skipped | skipped, con la nota Todo (estados) |
context.skip('why') | skipped: Vitest no escribe ningún motivo | skipped, con la nota Skipped: why |
Fallos de expect.soft | El mensaje del primer fallo | Cada fallo del intento, en las notas |
| Salida de consola | --attach-output: el <system-out> y el <system-err> de la prueba | captureOutput: stdout.log y stderr.log de cada intento (salida de consola) |
| Proyectos de Vitest | Ningún proyecto: la salida JUnit de Vitest no lo nombra | Un parámetro project en cada resultado, cuando la configuración tiene más de uno (proyectos de Vitest) |
| Errores no gestionados (Vitest 5) | Se dejan fuera, con una advertencia por archivo; --fail-on-failed-tests sale con 3 por ellos | Se dejan fuera, con una advertencia; el código de salida sigue siendo el de Vitest (errores fuera de una prueba) |
| Cuándo salen los resultados | Después de toda la ejecución, en un paso posterior | Al final de la ejecución, desde el paso de pruebas; un archivo de resultados guarda lo que no se pudo enviar |
Lo mismo en los dos caminos, así que ningún caso se mueve:
- Los estados de las pruebas aprobadas, fallidas y omitidas, incluido
test.fails, y las pruebas que.onlyo-tdejan fuera, que se omiten en los dos. - Los resultados fallidos de un
beforeAllo unafterAllque lanza un error, y de un archivo que no carga, con los nombres que les da el escritor JUnit de Vitest (errores fuera de una prueba). - Los IDs de caso en los títulos de las pruebas y de los
describe, los nombres de las filas detest.eachytest.for, y un>con un espacio a cada lado dentro de un título (nombres tal como los escribe Vitest).
Lo que la importación no puede saber
Sección titulada «Lo que la importación no puede saber»El XML contiene el nombre, el resultado, el tiempo y la salida de cada prueba. Lo que las pruebas le cuentan al reporter, y lo que Vitest le da más allá de su salida JUnit, nunca llega a la importación:
- Cada intento de una prueba reintentada o repetida, cada uno con su estado, su duración y sus errores.
- Los IDs de caso de
probara.id(), que viven en los metadatos propios de la prueba, no en su título (vincular). - Los pasos, anidados, con su estado y su duración, y los pasos de un caso nuevo (pasos).
- Los archivos:
probara.attach(), los archivos del propiocontext.annotate()de Vitest, las capturas de pantalla de los fallos en modo navegador (adjuntos). - Los parámetros, los comentarios, los enlaces y los campos de un caso nuevo: los helpers
probara.*(metadatos y enlaces). - La selección de pruebas: ejecutar solo las pruebas de una ejecución de Probara (selección de pruebas).
Conserva la importación donde el reporter no puede ejecutarse: un job que solo recibe el XML de otro job, o un Vitest anterior a 3.2, que el reporter no admite (la importación se prueba con Vitest 3.2, 4.1 y 5.0). El lado de la importación está en la CLI y en Vitest JUnit.
Casos creados por una importación anterior
Sección titulada «Casos creados por una importación anterior»probara import junit lee la salida de Vitest con su dialecto vitest, que detecta por la raíz del
informe (vitest tests), sin ninguna opción. Las versiones de la CLI anteriores a ese dialecto
(0.3.0 y anteriores) leen el mismo XML como JUnit genérico, que da a cada prueba la misma clave, con
dos diferencias:
| Resultado | JUnit genérico (la CLI 0.3.0 y anteriores) | El reporter, y el dialecto vitest |
|---|---|---|
| Un fallo con el nombre de su archivo, como un archivo que no carga | Con la clave del archivo solo: tests/broken.test.ts | El archivo dos veces: tests/broken.test.ts > tests/broken.test.ts |
| Un error no gestionado (Vitest 5) | Un resultado fallido propio | Se deja fuera, con una advertencia |
Solo se mueven esos resultados: el siguiente fallo de un archivo así crea un caso con su clave nueva, y el caso anterior no recibe más resultados. Todas las demás pruebas conservan su caso.
Desde Qase
Sección titulada «Desde Qase»Pasar de vitest-qase-reporter es sobre todo cambiar nombres: la entrada del reporter, sus ajustes y
las llamadas ctx.qase, que se convierten en llamadas probara.* sin el envoltorio withQase().
Esta sección relaciona cada una tal como la tiene el código de Qase (versión 1.5.1), que en algunos
puntos difiere de su documentación
(documentado, pero no en el código), y después recoge lo que
funciona de otra manera y lo que no se porta, con los motivos.
npm uninstall vitest-qase-reporter && npm i -D @probara/vitest-reporter.- En
vitest.config.mts, sustituye['vitest-qase-reporter', {...}]por['@probara/vitest-reporter', {...}], traduciendo las opciones (abajo). Eliminaqase.config.jsony.qaserc: el reporter solo lee sus opciones y las variablesPROBARA_*. Quitavitest-qase-reporter/setupdesetupFilessi lo añadiste: el reporter añade su propio archivo de setup. - Sustituye en CI las variables
QASE_*por variablesPROBARA_*: como mínimoPROBARA_API_TOKEN(un token de aplicación de la tarjeta Vitest, primeros pasos) yPROBARA_PROJECT. - Importa
probarade@probara/vitest-reporter, vuelve a convertir cadawithQase(async ({ qase }) => {...})en una función de prueba normal, y traduce las llamadas (abajo). Los IDs de caso pasan a ser IDs visibles de Probara (SHOP-12), no números.
Antes:
// vitest.config.mtsimport { defineConfig } from 'vitest/config';
export default defineConfig({ test: { reporters: [ 'default', [ 'vitest-qase-reporter', { mode: 'testops', testops: { project: 'SHOP', run: { title: 'Nightly', complete: true, tags: ['nightly'] }, uploadAttachments: true, }, }, ], ], },});Después:
// vitest.config.mtsimport { defineConfig } from 'vitest/config';
export default defineConfig({ test: { reporters: [ 'default', [ '@probara/vitest-reporter', { projectId: 'SHOP', run: { name: 'Nightly', tags: ['nightly'] }, captureOutput: true }, ], ], },});captureOutput es opcional: adjunta la salida de consola de cada intento, algo que el captureLogs
de Qase nunca hizo con Vitest
(salida de consola).
La ejecución se cierra al final sin complete: true, y uploadAttachments está activado por
defecto.
Opciones y variables de Qase
Sección titulada «Opciones y variables de Qase»Opción de Qase (variable QASE_*) | Opción de Probara (variable PROBARA_*) |
|---|---|
mode: 'testops' (QASE_MODE) | Activado siempre que haya un token y un proyecto |
mode: 'off' | enabled: false (PROBARA_ENABLED=false), o sin token |
mode: 'report', fallback (QASE_FALLBACK) | resultsFile (PROBARA_RESULTS_FILE) (archivo de resultados) |
report.connections.local.path, .format (QASE_REPORT_CONNECTION_PATH, _FORMAT) | resultsFile, la ruta de un archivo JSON |
mode: 'testops_multi', testops_multi.* | projectId más projects y run.ulids (varios proyectos) |
debug (QASE_DEBUG) | debug (PROBARA_DEBUG) |
environment (QASE_ENVIRONMENT), un slug, que se ignora si no se encuentra | 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): el reporter de Vitest de Qase lo ignora | captureOutput (PROBARA_CAPTURE_OUTPUT) |
statusMapping (QASE_STATUS_MAPPING) | statusMapping (PROBARA_STATUS_MAPPING), sin invalid ni disabled |
logging.console, logging.file (QASE_LOGGING_CONSOLE, QASE_LOGGING_FILE) | Los registros van 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 (QASE_TESTOPS_API_TIMEOUT), en segundos | timeoutMs, en milisegundos, para cada petición |
testops.api.retries, testops.api.retryBackoff | maxRetries, para cada petición; el backoff es fijo (reintentos y backoff) |
testops.project (QASE_TESTOPS_PROJECT) | projectId (PROBARA_PROJECT) |
testops.uploadAttachments (QASE_TESTOPS_UPLOAD_ATTACHMENTS) | uploadAttachments (PROBARA_UPLOAD_ATTACHMENTS) |
testops.attachments.concurrency, .timeout | attachmentConcurrency; las subidas tienen al menos 120 s (tiempos máximos) |
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 (QASE_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 (QASE_TESTOPS_BATCH_SIZE) | chunkSize (de 1 a 500) |
| (ninguna) | run.milestone (PROBARA_MILESTONE): el reporter de Qase no tiene hito |
Los ajustes de Qase sin equivalente están en lo que no se porta. Todas las opciones de Probara están en la página de configuración.
Las llamadas ctx.qase
Sección titulada «Las llamadas ctx.qase»| Qase | Probara |
|---|---|
test(addQaseId('pays', [12]), ...), (Qase ID: 12) en un título | test('SHOP-12 pays', ...): un ID en el título o en un describe (vincular) |
addQaseId('pays', [12, 13]) | 'SHOP-12 SHOP-13 pays', o probara.id(['SHOP-12', 'SHOP-13']) |
addQaseProjects('pays', { WEB: [3] }), (Qase WEB: 3) en un título | WEB-3 en el título, con projects: ['WEB'] (varios proyectos) |
withQase(async ({ qase }) => {...}) | La propia función de prueba: probara encuentra por sí solo la prueba en curso |
await qase.title('...') | probara.title('...') |
await qase.suite('Payments - Cards') | probara.suite(['Payments', 'Cards']) |
await qase.fields({ severity: 'critical' }) | probara.fields({ severity: 'critical' }) |
await qase.tags('smoke', 'checkout') | probara.tags('smoke', 'checkout') |
await qase.comment('...') | probara.comment('...') |
await qase.parameters({...}), await qase.groupParameters({...}) | probara.parameters({...}) |
await qase.step('Pay', fn, 'Paid', 'card=visa') | await probara.step('Pay', fn, { expected: 'Paid', data: 'card=visa' }) |
await qase.attach({ paths: [a, b] }) | await probara.attach({ name, path }), una vez por archivo |
await qase.attach({ name, content, type }) | await probara.attach({ name, body, contentType }) |
await qase.annotate(message, options) | await context.annotate(message, options): el del propio Vitest; su archivo se envía (anotaciones de Vitest) |
(ninguna: el reporter de Vitest de Qase no tiene ignore) | probara.ignore() |
| (ninguna) | probara.link() y probara.issue() (enlaces e incidencias) |
Quita los marcadores (Qase ID: 12) de los títulos: el reporter los lee como texto, así que se
quedarían en la clave de automatización.
Antes:
import { test } from 'vitest';import { addQaseId, withQase } from 'vitest-qase-reporter/vitest';
test( addQaseId('pays with a card', [12]), withQase(async ({ qase }) => { await qase.fields({ severity: 'critical' }); await qase.tags('smoke'); await qase.step('Pay', async () => {}, 'The order is paid'); await qase.attach({ name: 'order.json', content: '{"id":1042}', type: 'application/json' }); }),);Después:
import { probara } from '@probara/vitest-reporter';import { test } from 'vitest';
test('SHOP-12 pays with a card', async () => { probara.fields({ severity: 'critical' }).tags('smoke'); await probara.step('Pay', async () => {}, { expected: 'The order is paid' }); await probara.attach({ name: 'order.json', body: '{"id":1042}', contentType: 'application/json', });});[ { "caseDisplayId": "SHOP-12", "automationKey": "tests/checkout.test.ts > pays with a card", "status": "passed", "steps": [{ "action": "Pay", "expected": "The order is paid", "status": "passed" }], "case": { "tags": ["smoke"], "fields": { "severity": "critical" }, "steps": [{ "action": "Pay", "expected": "The order is paid" }] } }]El resultado lleva además order.json (application/json). El ID sale del título y de la clave:
añadirlo o quitarlo nunca cambia el caso con el que coincide la prueba
(claves de automatización).
Documentado, pero no en el código
Sección titulada «Documentado, pero no en el código»El README y las guías de Qase muestran llamadas y ajustes que la versión 1.5.1 no tiene, o que tiene con otro comportamiento. El código copiado de ahí falla o hace otra cosa:
| Documentación de Qase | Código de Qase (1.5.1) | Con Probara |
|---|---|---|
test(qase(12, 'pays'), ...), con qase importado de vitest-qase-reporter o de vitest-qase-reporter/vitest | No se exporta ningún qase: solo withQase, addQaseId y addQaseProjects | test('SHOP-12 pays', ...) |
qase.title(), qase.fields(), qase.suite() sobre esa importación, en cualquier prueba | Solo ctx.qase, en una función que envuelve withQase() | probara.title(), probara.fields(), probara.suite(), en cualquier prueba |
qase.ignore() | No está en el código | probara.ignore() |
qase.mute() | No está en el código | No se porta (abajo) |
setupFiles: ['vitest-qase-reporter/setup'], para el perfilador de red | El paquete no lo exporta: Vitest no puede cargarlo | Nada que añadir: el reporter añade su propio archivo de setup |
qase.suite('Payments\tCards'), un tabulador entre suites | Solo divide por un guion con un espacio a cada lado ('Payments - Cards') | probara.suite(['Payments', 'Cards']) |
| Pasos anidados en pasos | Un paso que contiene pasos se pierde; solo se conservan los internos | Anidados tal como se ejecutaron (pasos) |
| Un adjunto de un paso | Siempre es de la prueba | probara.attach() dentro de un paso (archivos de un paso) |
Las opciones del reporter ganan a las variables QASE_*, que ganan a qase.config.json | Las variables ganan al archivo, que gana a las opciones | Las opciones y después las variables (precedencia) |
testops.run.complete vale true por defecto | Sin definir, deja la ejecución abierta | Una ejecución creada se cierra por defecto (cierre) |
report.connection.* | report.connections.* | resultsFile |
| El modo watch reporta al salir o al volver a ejecutar todas las pruebas | Cada nueva ejecución crea una ejecución nueva, salvo que se defina run.id | Una sola ejecución para toda la sesión (modo watch) |
api.token por proyecto de testops_multi | Un solo token para todos los proyectos | Un solo token de aplicación para todos los proyectos de la organización |
Qué es distinto respecto a Qase, y por qué
Sección titulada «Qué es distinto respecto a Qase, y por qué»| Tema | Qase | Probara |
|---|---|---|
| Precedencia | Las variables ganan a qase.config.json, que gana a las opciones del reporter | Las opciones de la configuración de Vitest, después las variables PROBARA_*, y 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 la configuración de Vitest |
| IDs de caso | Números, solo en el título de la propia prueba | IDs visibles (SHOP-12) en el título o en cualquier describe: el ID del Proyecto dirige cada ID a su proyecto |
| Los helpers | ctx.qase, dentro de withQase(), hasta que termina el cuerpo de la prueba: Vitest rechaza sus anotaciones en afterEach | probara, importado una vez, funciona en el cuerpo, en beforeEach, en afterEach, en onTestFinished y en las funciones a las que llaman (dónde llamarlos) |
| Pasos | Planos; el resultado esperado y los datos se codifican en el nombre del paso; sin duración | Anidados tal como se ejecutaron, cada uno con su estado, su duración y su error; los más externos pasan a ser los pasos de un caso nuevo (pasos) |
| 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. Sin suposiciones a partir del texto del error (estados) |
| Errores | El mensaje del primer error, que comment() sustituye; cada traza en un campo propio | Cada error del intento en las notas, incluidos los fallos de expect.soft; un comentario va primero y no oculta ninguno |
Llamadas a fields() y parameters() | La última llamada sustituye a las demás | Se combinan por nombre |
| 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 (solo casos creados) |
| Reintentos | Solo el intento final | Cada intento es un resultado, sin marca de inestable: el historial del caso muestra la inestabilidad (reintentos) |
| Cierre de la ejecución | Solo con run.complete: true; sin definir, queda abierta | Una ejecución que crea el reporter se cierra al final, cuando se envió todo; una reutilizada queda abierta (cierre) |
| Shards | Cada shard crea su propia ejecución salvo que reciba un ID de ejecución; cerrar una ejecución compartida queda para otro paso | Una sola ejecución: vitest --merge-reports sobre los blobs de los shards, o probara run create con PROBARA_RUN_ULID (sharding) |
| Cuando falla el envío | fallback a un informe local | Un archivo de resultados, que probara import results envía más tarde a las mismas ejecuciones (archivo de resultados) |
Cadenas en attach() | Una cadena que parece base64 se decodifica ('Hello' sube basura) | Una cadena se envía tal cual; pasa un Buffer o un Uint8Array para contenido binario (probara.attach()) |
attach({ paths }) | Una lista de rutas; el tipo de contenido es type, no contentType | Un archivo por llamada, path o body, y contentType |
Lo que no se porta de Qase
Sección titulada «Lo que no se porta de Qase»| Función de Qase | Por qué |
|---|---|
Enlace público al informe (showPublicReportLink) | Un enlace público a los resultados de las pruebas es una decisión de compartir que corresponde a la aplicación 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; reporta los defectos desde el resultado en Probara |
Perfilador de red (profilers: ['network'], networkProfiler) | Sus pasos no aportan nada, hasta los 200 pasos de un resultado, y no se pueden distinguir cuando las pruebas se ejecutan en paralelo; adjunta lo importante con probara.attach() (sin perfilador de red) |
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; probara.issue() vincula un resultado a una incidencia |
qase.mute() | Qase lo documenta, pero no está en su código; la clasificación vive en Probara, en los resultados |
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 |
El estado invalid | Es una suposición a partir del texto del error; Probara mantiene cuatro estados y el error completo en las notas |
Registrar en un archivo (logging.file) | Los registros van a stderr, donde los guarda el CI; redirige stderr para conservar un archivo |
Plan y entorno por proyecto (testops_multi.projects[].plan, .environment) | Las entidades de planificación pertenecen a un proyecto, donde un nombre desconocido rechazaría el informe: crea primero la ejecución de ese proyecto con probara run create y pásala en run.ulids (una ejecución por proyecto) |
Un archivo de configuración (qase.config.json, .qaserc) | Un archivo con un token podría subirse al repositorio: el token se queda en el entorno, y las opciones en la configuración de Vitest |
Desde Allure
Sección titulada «Desde Allure»allure-vitest es un reporter que añade su archivo de setup y su runner a cada proyecto de Vitest, y
escribe archivos de resultados en allure-results/; un paso aparte los convierte en un informe. El
reporter envía en cambio los resultados a Probara, y añade su propio archivo de setup y su runner del
mismo modo: cambia las entradas.
// vitest.config.mtsimport { defineConfig } from 'vitest/config';
export default defineConfig({ test: { reporters: [ 'default', [ 'allure-vitest/reporter', { resultsDir: 'allure-results', links: { issue: { urlTemplate: 'https://jira.example.com/browse/%s' } }, }, ], ], },});Ajustes de Allure
Sección titulada «Ajustes de Allure»| Allure | Probara |
|---|---|
resultsDir | Nada: los resultados van a Probara. Un archivo de resultados guarda lo que no se pudo enviar |
links.issue.urlTemplate | issueUrlTemplate (PROBARA_ISSUE_URL_TEMPLATE) (probara.issue()) |
environmentInfo | run.environment (un nombre) y el origen de la ejecución, detectado del CI (la ejecución) |
globalLabels, ALLURE_LABEL_* | run.tags (PROBARA_RUN_TAGS) para la ejecución; las etiquetas de un caso nuevo salen de probara.tags() |
ALLURE_TESTPLAN_PATH | runCasesOnly con PROBARA_RUN_ULID (selección de pruebas) |
reportMatchers, categories, listeners | No se portan (lo que el reporter no admite) |
Llamadas de Allure
Sección titulada «Llamadas de Allure»Las llamadas de Allure son asíncronas (await allure.tags('smoke')); las de Probara vuelven en el
acto, salvo probara.attach() y un probara.step() con un cuerpo asíncrono, que esperas con
await.
Allure (allure-js-commons) | Probara (probara.*) |
|---|---|
@allure.id:12 en un título, allureId('12') | SHOP-12 en el título o en un describe, o id('SHOP-12') |
displayName('...') | title('...') |
description('...') | fields({ description: '...' }) |
severity('critical'), layer('api') | fields({ severity: 'critical', layer: 'api' }) |
tag('smoke'), tags(...) | tags('smoke') |
epic, feature, story, label(name, value) | fields({ Feature: 'Checkout' }): un campo personalizado con ese nombre, o tags(...) |
parentSuite, suite, subSuite | suite(['Payments', 'Cards']) |
parameter('user', 'ana') | parameters({ user: 'ana' }) |
step('Pay', async () => {...}) | step('Pay', async () => {...}) |
logStep('Paid') | step('Paid'): un paso sin cuerpo, aprobado |
attachment(name, content, { contentType }) | attach({ name, body: content, contentType }) |
attachmentPath(name, path) | attach({ name, path }) |
link(url, name) | link(url, name) |
issue('PAY-7') | issue('PAY-7'), con issueUrlTemplate |
tms('12') | id('SHOP-12') |
reporters: [ 'default', ['@probara/vitest-reporter', { issueUrlTemplate: 'https://jira.example.com/browse/%s' }],],import { probara } from '@probara/vitest-reporter';import { test } from 'vitest';
test('refunds an order', async () => { probara.fields({ severity: 'critical' }).issue('PAY-7'); await probara.step('Open the order', async () => {}); await probara.step('Refund it', async () => {});});[ { "automationKey": "tests/payments.test.ts > refunds an order", "steps": [ { "action": "Open the order", "status": "passed" }, { "action": "Refund it", "status": "passed" } ], "links": [{ "url": "https://jira.example.com/browse/PAY-7", "name": "PAY-7" }], "case": { "fields": { "severity": "critical" }, "steps": [{ "action": "Open the order" }, { "action": "Refund it" }] } }]Qué funciona distinto respecto a Allure
Sección titulada «Qué funciona distinto respecto a Allure»| Tema | Allure | Probara |
|---|---|---|
| Estados | failed para una aserción, broken para cualquier otro error | failed para ambos, con el error en las notas: sin suposiciones a partir del tipo de error (estados) |
test.skip, un describe omitido | No se reportan | Resultados omitidos, como los tiene la salida JUnit de Vitest |
| Aserciones | Cada expect es un paso (reportMatchers, activado por defecto) | Los pasos son las llamadas a probara.step() |
| Una llamada donde no corre ninguna prueba | Una llamada en beforeAll o en el cuerpo de un describe va a cada prueba de la suite | Se deja fuera, con una advertencia: ahí no corre una sola prueba (dónde llamar a los helpers) |
| Un hook que lanza un error | Su error es un error global del informe, junto a las pruebas | El veredicto de Vitest: un beforeEach o afterEach que falla hace fallar su prueba, un beforeAll o afterAll que falla es un resultado fallido de su describe o de su archivo (errores fuera de una prueba) |
| Reintentos | Un resultado por prueba, el intento final | Cada intento es un resultado de la ejecución (reintentos) |
| Modo watch | Archivos de resultados nuevos en cada nueva ejecución, que se acumulan en resultsDir | Una sola ejecución para toda la sesión (modo watch) |
| Campos del caso | Etiquetas en cada resultado | Campos y etiquetas del caso que crea un informe; un caso existente conserva los suyos (solo casos creados) |
test.concurrent en modo navegador | Una llamada puede ir a la prueba equivocada después de un await (lo dice su README) | Una llamada se descarta con una advertencia, nunca se registra en otra prueba (modo navegador) |
Desde ReportPortal
Sección titulada «Desde ReportPortal»@reportportal/agent-js-vitest es un objeto reporter en reporters, con un archivo de setup que
listas en setupFiles para su ReportingApi. Sustituye ambos por la entrada del reporter de
arriba:
// vitest.config.mtsimport RPReporter from '@reportportal/agent-js-vitest';import { defineConfig } from 'vitest/config';
export default defineConfig({ test: { setupFiles: ['@reportportal/agent-js-vitest/setup'], reporters: [ 'default', new RPReporter({ apiKey: process.env.RP_API_KEY, endpoint: 'https://rp.example.com/api/v2', project: 'shop', launch: 'Nightly', }), ], },});Ajustes de ReportPortal
Sección titulada «Ajustes de ReportPortal»| ReportPortal (variable) | Probara (variable) |
|---|---|
apiKey, oauth | PROBARA_API_TOKEN: un token de aplicación de la tarjeta Vitest (primeros pasos) |
endpoint | baseUrl (PROBARA_BASE_URL), la URL de la aplicación sin ruta |
project | projectId (PROBARA_PROJECT) |
launch | run.name (PROBARA_RUN_NAME) |
description | run.description (PROBARA_RUN_DESCRIPTION) |
attributes ([{ key: 'build', value: '42' }]) | run.tags (PROBARA_RUN_TAGS=build:42,nightly): las etiquetas son nombres simples, con dos puntos incluidos |
launchId (RP_LAUNCH_ID) | run.ulid (PROBARA_RUN_ULID) |
launchUuidPrint | probara run create imprime el ULID en el que reporta cada shard (una ejecución existente) |
restClientConfig (timeout, retries, proxy) | timeoutMs, maxRetries; un proxy mediante las variables de Node (red) |
headers | Un fetch propio (tu propio cliente HTTP) |
debug | debug (PROBARA_DEBUG) |
extendTestDescriptionWithLastError | Nada que definir: cada error de un intento está en sus notas |
skippedIssue, rerun, rerunOf, mode: 'DEBUG' | No se portan (lo que el reporter no admite) |
Llamadas de ReportPortal
Sección titulada «Llamadas de ReportPortal»ReportPortal (ReportingApi) | Probara (probara.*) |
|---|---|
ReportingApi.attachment(task, { name, type, content }) | attach({ name, body, contentType }), con un Buffer o texto, o attach({ name, path }) |
ReportingApi.description(task, text) | fields({ description: text }), para un caso nuevo |
ReportingApi.attributes(task, [{ key, value }]) | parameters({ [key]: value }) en el resultado, o tags(value) en un caso nuevo |
ReportingApi.testCaseId(task, id) | No se porta: vincula un caso por su ID (vincular) |
ReportingApi.log(task, message, level) | No se porta: comment() para una línea en las notas, captureOutput para la consola |
console.log(), console.error(), como registros | captureOutput: stdout.log y stderr.log de cada intento (salida de consola) |
El ReportingApi global del archivo de setup | probara, importado: no hay ningún task que pasar |
Una cadena en base64 como content se enviaría como texto: pasa a attach() la path del archivo,
o sus bytes como un Buffer.
import { probara } from '@probara/vitest-reporter';import { test } from 'vitest';
test('pays with a card', async () => { probara.fields({ description: 'Pays with a saved card' }).parameters({ browser: 'chromium' }); await probara.attach({ name: 'response', body: '{"status":"paid"}', contentType: 'application/json', });});[ { "automationKey": "tests/checkout.test.ts > pays with a card", "parameters": { "browser": "chromium" }, "case": { "description": "Pays with a saved card" } }]El resultado lleva además response.json (application/json).
Qué funciona distinto respecto a ReportPortal
Sección titulada «Qué funciona distinto respecto a ReportPortal»| Tema | ReportPortal | Probara |
|---|---|---|
| API dentro de la prueba | ReportingApi, global desde su archivo de setup, o pasando el task de la prueba | probara, importado; cada llamada pertenece a la prueba que la hizo (metadatos) |
test.concurrent | El ReportingApi global sigue a la última prueba que empezó, así que una llamada puede ir a otra prueba | Cada llamada va a su propia prueba |
| Reintentos | Solo el intento final | Cada intento es un resultado (reintentos) |
test.todo | Omitida, con el atributo todo | Omitida, con la nota Todo |
Un describe omitido | Un elemento de suite omitido; sus pruebas no se reportan | Cada prueba es un resultado omitido |
| Errores | El primer error, como registro y en la descripción | Cada error del intento, en las notas de su resultado |
| Estructura | Un elemento de suite por cada describe | Cada caso nuevo en una suite con el nombre de su archivo (casos que faltan) |
| Modo watch | El launch termina con la primera ejecución, y las siguientes no tienen ninguno | Una sola ejecución para toda la sesión (modo watch) |
Desde TestRail
Sección titulada «Desde TestRail»TestRail no tiene reporter para Vitest: un pipeline escribe la salida JUnit de Vitest, y después la
CLI de Python de TestRail, trcli parse_junit, la envía tras la ejecución. El reporter sustituye
ambos pasos, y envía lo que el XML no puede contener: pasos, archivos, comentarios y cada intento.
npx vitest run --reporter=junit --outputFile=reports/vitest.xmltrcli -h https://example.testrail.io --project "Shop" -u ci@example.com -k "$TESTRAIL_KEY" \ parse_junit --title "Nightly" --case-matcher name -f reports/vitest.xml --close-runCon el reporter, basta con el paso de pruebas:
npx vitest runAjustes de trcli
Sección titulada «Ajustes de trcli»| trcli | Probara |
|---|---|
-h (host), -u, -p, -k | baseUrl para un Probara autoalojado; PROBARA_API_TOKEN |
--project (un nombre) | projectId (PROBARA_PROJECT), el ID del Proyecto |
--title, --run-description | run.name, run.description |
--run-id | run.ulid (PROBARA_RUN_ULID) |
--plan-id, --config-ids, --milestone-id | run.plan, run.configurations, run.milestone, por ID visible o nombre (la ejecución) |
--close-run | El comportamiento por defecto para una ejecución que crea el reporter; closeRun para una reutilizada |
--case-matcher name (C123 en el nombre) | SHOP-12 en el título o en un describe (vincular) |
--case-matcher auto (classname.name) | La clave de automatización: el archivo, los describes y el título |
-y (crear secciones y casos) | createMissingCases, activado por defecto; las suites salen del archivo de prueba |
--suite-id, --section-id | suiteUlid (PROBARA_SUITE_ULID): la suite bajo la que van los casos creados |
--case-fields type_id:3 | probara.fields({ type: 'Regression' }) en la prueba, por nombre (metadatos) |
-a, --assign (emails) | assignFailedTo (PROBARA_ASSIGN_FAILED_TO) (asignar resultados fallidos) |
-b, --batch-size | chunkSize (de 1 a 500) |
-t, --timeout (segundos) | timeoutMs (milisegundos, para cada intento de una petición) |
--proxy, --noproxy | HTTPS_PROXY y NO_PROXY con NODE_USE_ENV_PROXY=1 (proxies) |
-v (verbose) | debug (PROBARA_DEBUG) |
Propiedad testrail_result_comment | probara.comment() |
Propiedad testrail_attachment | probara.attach() |
Propiedad testrail_result_step | probara.step() |
Qué funciona distinto respecto a trcli
Sección titulada «Qué funciona distinto respecto a trcli»| Tema | trcli sobre la salida JUnit de Vitest | Probara |
|---|---|---|
| Pruebas omitidas | Retest | Omitidas |
test.todo | Retest: Vitest la escribe como omitida | Omitida, con la nota Todo |
| Reintentos | Un resultado por prueba | Cada intento (reintentos) |
| Describes anidados | Una sección por archivo de prueba, plana: Vitest escribe una suite por archivo | La suite de un caso creado es su archivo; probara.suite() nombra suites anidadas |
| Duraciones | Redondeadas a segundos (--allow-ms para milisegundos) | Milisegundos, y el inicio de cada intento |
| Un ID de caso desconocido | Aborta la subida | Ese resultado no se registra, y el registro lo nombra; los demás sí |
| Una subida fallida | Deshace la ejecución, los casos y las secciones que creó | No se deshace nada; un archivo de resultados guarda lo que no se envió |
| Shards | Una subida del archivo de cada shard, con un patrón | vitest --merge-reports sobre los blobs, o probara run create, PROBARA_RUN_ULID en cada shard y probara run close (sharding) |
Lo que el reporter no admite
Sección titulada «Lo que el reporter no admite»Cada una de estas funciones se deja fuera, con su motivo:
| Función | En | Por qué |
|---|---|---|
| Actualizar casos existentes | trcli (--update-existing-cases, --update-strategy) | Un informe nunca cambia un caso existente: lo que hay escrito ahí es de las personas (solo casos creados) |
| Una marca de inestable | Vitest (diagnostic().flaky) | Cada intento es un resultado: un caso cuyo historial mezcla fallos y aprobados en una ejecución es inestable, sin necesidad de marca (reintentos) |
| Aserciones como pasos | Allure (reportMatchers) | Cada expect sería un paso, hasta los 200 pasos de un resultado, y desplazaría a los pasos que dicen lo que hace la prueba: envuelve lo importante en probara.step() |
Los estados broken e invalid | Allure (broken), Qase (invalid) | Los dos son una suposición a partir del tipo o del texto del error; Probara mantiene cuatro estados (passed, failed, skipped, blocked) y el error completo en las notas |
| Parámetros enmascarados, ocultos y excluidos | Allure (los modos de parameter()) | Los parámetros se muestran con el resultado y nunca forman parte de la clave: deja fuera un secreto en lugar de enmascararlo |
| Niveles de registro y una API de registro | ReportPortal (ReportingApi.log()), Allure (logStep() con un estado) | Probara no tiene una entidad de registro: captureOutput guarda la salida de consola de cada intento, probara.comment() escribe una línea en las notas, y el estado de un paso es lo que hizo su cuerpo |
| Defectos, enlaces de Jira en las ejecuciones, enlaces públicos a informes | Qase (testops.defect, run.externalLink, showPublicReportLink) | Los defectos y su clasificación viven en Probara, en los resultados; probara.issue() vincula un resultado a una incidencia; un enlace público a los resultados es una decisión de compartir, no un ajuste de CI |
| Un perfilador de red | Qase (profilers: ['network']) | Sus pasos no aportan nada, hasta los 200 pasos de un resultado, y no se pueden distinguir cuando las pruebas se ejecutan en paralelo (sin perfilador de red) |
| Categorías, problemas conocidos, pruebas silenciadas | Allure (categories), ReportPortal (skippedIssue), Qase (qase.mute(), solo documentado) | La clasificación vive en Probara, en los resultados y los defectos, no en un ajuste de CI |
| Sustituir la clave de automatización | Allure (historyId(), testCaseId()), ReportPortal (testCaseId()), trcli (custom_automation_id) | La clave sale del archivo y de los nombres, igual que la de probara import junit: vincula un caso por su ID (claves de automatización) |
| Un propietario | Allure (owner()) | Un caso de Probara no tiene campo de propietario: asigna en su lugar los resultados fallidos (asignar resultados fallidos) |
| Campos de resultado | trcli (--result-fields, testrail_result_field) | Los resultados de Probara no tienen campos personalizados: los parámetros (probara.parameters()) y los enlaces (probara.link()) llevan los datos adicionales |
| Pasos y llamadas desde los hooks de una suite | Allure (una llamada en beforeAll va a cada prueba de la suite) | Una llamada donde no corre una sola prueba no pertenece a ninguna prueba: se deja fuera con una advertencia, no se copia en cada una. Crea los pasos importantes en la prueba o en su beforeEach; un hook que lanza un error se sigue mostrando (errores fuera de una prueba) |
| Un archivo de configuración | Qase (qase.config.json, .qaserc), trcli (config.yml) | Un archivo con un token podría subirse al repositorio: el token se queda en el entorno, y las opciones en la configuración de Vitest (configuración) |
| Benchmarks y cobertura | Vitest (vitest bench, --coverage) | Probara no tiene resultados de benchmarks ni de cobertura: el reporter envía resultados de pruebas |
| Pruebas de tipos | Vitest (vitest typecheck) | Ninguna prueba del reporter las cubre, así que no se promete nada para ellas |
| Launches de repetición y de depuración | ReportPortal (rerun, rerunOf, mode: 'DEBUG') | Vuelve a reportar en la misma ejecución con run.ulid: cada caso de la ejecución conserva el último resultado y su historial. Para probar una configuración, comprueba qué se enviaría |
| Iniciar sesión con OAuth | ReportPortal (oauth) | El CI reporta con un token de aplicación de la organización, que no ocupa ningún puesto y sobrevive a la persona que lo creó |
| Archivos y errores globales | Allure (globalAttachment(), globalError()) | Los archivos y los errores pertenecen a un resultado: adjúntalos desde la prueba que los produjo |
| Descripciones en HTML | Allure (descriptionHtml()) | La descripción es texto; Probara le da formato |
| Listeners | Allure (listeners) | Ningún hook cambia un resultado antes de enviarlo; statusMapping y statusFilter cubren los estados (mapeo de estados) |
| Desactivar la verificación TLS | trcli (--insecure) | No se puede desactivar: pasa a Node tu autoridad de certificación (autoridades de certificación propias) |
| Deshacer una subida fallida | trcli | Un resultado registrado se conserva: deshacerlo perdería los que sí llegaron |
| Referencias en las ejecuciones | trcli (--test-run-ref) | La ejecución registra la URL del build de CI, la rama y el commit; las incidencias se vinculan a los resultados con probara.issue() |
Actualizar el reporter
Sección titulada «Actualizar el reporter»@probara/vitest-reporter sigue el versionado semántico. Lee el
changelog
antes de actualizarlo. Una versión mayor nueva de Vitest puede cambiar los nombres que da a las
pruebas, y con ellos sus claves de automatización: antes de actualizar Vitest, lee
de Vitest 4 a 5 y
compara las claves.
- 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/vitest-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 otro significado. - Un valor por defecto cambiado (cerrar ejecuciones, crear los casos que faltan,
keyIncludesFile, lo que se adjunta). - Un helper
probara.*eliminado, o con otro comportamiento. - Un estado con el que se envía un intento, cambiado para el mismo intento.
- Cualquier cambio en la clave de automatización que recibe una prueba, con
keyIncludesFileactivado o desactivado. Una clave distinta desvincula la prueba de su caso: la siguiente ejecución crea uno nuevo. - Dejar de admitir una versión de Vitest o de Node.js que sigue teniendo soporte de sus autores.
Añadir una opción, un helper, una línea de registro o un archivo que se sube no es incompatible. Las líneas del registro en 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 de la clave 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 Vitest se convierte en las partes de la
clave, igual que probara import junit lee la salida JUnit de Vitest
(claves):
- el archivo de prueba relativo a
rootDir(la raíz de Vitest), cuandokeyIncludesFileestá activado; - los títulos de los
describey el de la prueba, cada uno una parte, como los nombra la salida JUnit de Vitest, sin los IDs de caso; - una fila de
test.eachotest.for, por el título que le da el formato de Vitest.
Esa correspondencia también forma parte del contrato: una versión del reporter que cambia la clave
de una prueba es un cambio incompatible, señalado como tal en el changelog. Una versión de Vitest
que formatea los títulos de otra forma también cambia claves (abajo), tanto para el reporter como
para probara import junit.
Para comprobar una actualización de cualquiera de los dos, compara lo que enviarían ambas versiones:
ejecuta la batería con el envío desactivado una vez por versión, cada una con su propio archivo de
resultados, y compara las simulaciones con diff
(comprobar qué se enviaría).
Cualquier clave que cambie es una prueba que recibiría un caso nuevo.
Versiones de Vitest y de Node.js
Sección titulada «Versiones de Vitest y de Node.js»| Necesita | Versiones admitidas |
|---|---|
vitest | 3.2 y posteriores (el rango de peer ^3.2.0 || ^4.0.0 || ^5.0.0): probado en 3.2.7, 4.1.11, 5.0.2 |
| Modo navegador | El proveedor de tu versión de vitest: probado en 3.2.7, 4.0.18, 4.1.11 y 5.0.2 |
| Node.js | 22.12 y posteriores (el campo engines) |
Vitest 3.2 es la primera versión con anotaciones de prueba, que el reporter lee, de ahí el rango de
peer. El modo navegador tiene su propia configuración por cada línea de Vitest
(modo navegador). 0.1.0 es la primera
versión del reporter: todavía no hay nada desde lo que migrar, y si vienes de probara import junit
sobre la salida JUnit de Vitest, las claves se mantienen.
De Vitest 4 a 5
Sección titulada «De Vitest 4 a 5»Cambian algunos títulos de test.each y test.for, y con ellos sus claves. Vitest 5 formatea
de otra manera los valores que pone en un título:
| La prueba | Vitest 3 y 4 | Vitest 5 |
|---|---|---|
test.each([{ name: 'Ana' }])('greets $name') | greets 'Ana' | greets Ana |
test.each([{ note }])('saves $note'), una nota de 48 caracteres | saves 'Leave the parcel with the neighbour a…' | saves Leave the parcel with the neighbour at … |
test.each([[{ note }]])('stores %o') | stores { note: 'Leave the parcel with the neighbour at number 12' } | stores { …(1) } |
test.each([[new Map([['eur', 12]])]])('reads %o') | reads Map{ 'eur' => 12 } | reads Map { 'eur' => 12 } |
Números, objetos y arrays cortos, %s de una cadena | Igual | Igual |
Las claves de esas filas, tal como las nombra Vitest 5:
import { test } from 'vitest';
const note = 'Leave the parcel with the neighbour at number 12';
test.each([{ name: 'Ana' }])('greets $name', () => {});
test.each([[{ note }]])('stores %o', () => {});[ { "automationKey": "tests/rows.test.ts > greets Ana" }, { "automationKey": "tests/rows.test.ts > stores { …(1) }" }]- Una clave que cambia es un caso nuevo. El caso anterior conserva su historial, y los resultados de la clave nueva van a un caso nuevo. Compara las claves antes de actualizar, como arriba: cada línea que cambia es una de esas filas.
- Las filas pueden coincidir.
{ …(1) }representa cualquier objeto de una sola clave demasiado largo para imprimirse, así que dos filas así reciben el mismo título y comparten un caso. Pon en el título un valor corto de cada fila ('stores $id'). probara import junitcambia del mismo modo: lee los nombres que Vitest 5 escribe en su salida JUnit, así que los dos caminos siguen dando a una prueba la misma clave.- Las carpetas por defecto cambian:
attachmentsDirpasa de.vitest-attachmentsa.vitest/attachments(dónde se guardan las copias), y los blobs de un job con sharding pasan de.vitest-reportsa.vitest/blob, que es lo que leevitest --merge-reportspor defecto. Un job de CI que los lleva, o que los limpia, necesita las rutas nuevas (lleva los blobs y los adjuntos).
De Vitest 3 a 4
Sección titulada «De Vitest 3 a 4»- El modo navegador tiene un paquete de proveedor nuevo,
@vitest/browser-playwright, conprovider: playwright()(modo navegador). - Las etiquetas de Vitest (4.1 y posteriores) se suman a las etiquetas de los casos que crea un informe; Vitest rechaza una etiqueta que su configuración no declara (etiquetas de Vitest).
- Los cuerpos de texto de
context.annotate()necesitanbodyEncoding: 'utf-8'a partir de Vitest 4.1.3: si no, Vitest marca el cuerpo como base64 (anotaciones de Vitest).
Cualquier actualización de un pipeline con sharding
Sección titulada «Cualquier actualización de un pipeline con sharding»vitest --merge-reports solo lee los blobs de su propia versión de Vitest: actualiza a la vez los
shards y el job que fusiona, en un único cambio del pipeline
(la misma versión de Vitest en todas partes).
Relacionado: Primeros pasos · Vincular · CLI · Fuente: migrating-from-junit.md, migrating-from-qase.md, coming-from-other-tools.md, upgrade.md