Ir al contenido

Resultados, estados y reintentos en Vitest

Cada vitest run reporta en una ejecución de Probara: una ejecución automatizada nueva por defecto, cerrada al final, o una existente. Cada ejecución de cada prueba es un resultado en ella, con el veredicto del propio Vitest. Esta página cubre la ejecución, los estados, los reintentos y las repeticiones, qué pasa cuando no se pueden enviar los resultados, y quién recibe los fallos.

Estas opciones describen la ejecución que crea el reporter:

reporters: [
'default',
[
'@probara/vitest-reporter',
{
run: {
name: 'Nightly regression',
description: 'Every night on main, against staging.',
environment: 'staging',
milestone: 'Sprint 12',
plan: 'PLAN-2',
configurations: [
{ group: 'Node', name: '22' },
{ group: 'OS', name: 'Linux' },
],
tags: ['nightly', 'unit'],
},
},
],
],
OpciónVariableQué define
run.namePROBARA_RUN_NAMEEl nombre. Por defecto: el nombre del build de CI (CI #42), si no Automated run <date> <time> UTC
run.descriptionPROBARA_RUN_DESCRIPTIONLa descripción, hasta 2000 caracteres (lo que exceda se recorta, con una advertencia)
run.environmentPROBARA_ENVIRONMENTEl entorno, por nombre: se crea en el proyecto si ninguno tiene ese nombre
run.milestonePROBARA_MILESTONEEl hito, por ID visible (M-3) o nombre exacto
run.planPROBARA_PLANEl plan de pruebas, por ID visible (PLAN-2) o nombre exacto: la ejecución empieza con los casos del plan
run.configurationsPROBARA_CONFIGURATIONSValores de configuración por grupo y nombre (Node=22,OS=Linux), cada grupo una vez
run.tagsPROBARA_RUN_TAGSEtiquetas (nightly,unit), hasta 50

La misma ejecución desde el entorno de un paso de CI, con el proyecto en la configuración:

Ventana de terminal
PROBARA_RUN_NAME="Nightly regression" PROBARA_ENVIRONMENT=staging PROBARA_RUN_TAGS=nightly,unit npx vitest run

Los projects de Vitest no cambian la ejecución: todos los proyectos de la configuración reportan en la misma ejecución, y un resultado nombra su proyecto de Vitest en el parámetro project cuando la configuración tiene más de uno (proyectos de Vitest).

El entorno, el hito y las configuraciones también aceptan ULIDs: run.environmentId, run.milestoneId y run.configurationUlids (PROBARA_ENVIRONMENT_ID, PROBARA_MILESTONE_ID, PROBARA_CONFIGURATION_ULIDS). Define una sola forma de cada uno, nunca ambas: las dos a la vez son un problema de configuración que desactiva el envío. Los nombres son la forma que hay que usar con un token de aplicación, que no puede buscar ULIDs.

  • Un nombre de entorno desconocido crea el entorno.
  • Un hito, un plan o una configuración desconocidos hacen que Probara rechace el primer informe (422, nombrando el campo): no se registra nada, y el registro dice por qué. Comprueba los nombres en Probara.

Una ejecución registra de dónde viene: la rama, el commit y la URL del build de CI, leídos de las variables de GitHub Actions, GitLab CI, CircleCI, Azure Pipelines, Jenkins, Bitbucket Pipelines y Buildkite (lo que rellena cada CI). Sustituye un campo con source o con su variable, o no envíes ninguno:

reporters: ['default', ['@probara/vitest-reporter', { source: { branch: 'release/2.4' } }]],
OpciónVariableValor por defecto
source.branchPROBARA_BRANCHdetectado del CI
source.commitPROBARA_COMMITdetectado del CI
source.buildUrlPROBARA_BUILD_URLdetectado del CI
source: false—no envía origen

El nombre del build de CI también da nombre a la ejecución cuando run.name no está definido.

run.ulid (PROBARA_RUN_ULID) reporta en una ejecución que ya existe, como una que probara run create creó para los shards de un pipeline (sharding), o una que una persona creó en Probara (selección de pruebas). El reporter añade sus resultados a esa ejecución y la deja abierta:

$ PROBARA_RUN_ULID=01J9Z3K4M5N6P7Q8R9S0T1V2W3 npx vitest run
[probara] Sending 3 results of 3 tests (3 passed, 0 failed, 0 skipped, 0 blocked)
[probara] Recorded 3 results (2 new cases, 0 unmatched) in R-1 (open): https://app.probara.net/projects/SHOP/runs/R-1

Las opciones de una ejecución nueva se ignoran entonces, con una advertencia: la ejecución conserva su propio nombre, entorno, hito y configuraciones.

reporters: ['default', ['@probara/vitest-reporter', { run: { name: 'Nightly regression' } }]],
$ PROBARA_RUN_ULID=01J9Z3K4M5N6P7Q8R9S0T1V2W3 npx vitest run
[probara] Ignored name: a reused run (run.ulid) keeps its own
[probara] Sending 3 results of 3 tests (3 passed, 0 failed, 0 skipped, 0 blocked)
[probara] Recorded 3 results (2 new cases, 0 unmatched) in R-1 (open): https://app.probara.net/projects/SHOP/runs/R-1

Para obtener el ULID de una ejecución en Probara, abre la ejecución y elige Copiar ULID de la ejecución en Acciones de la ejecución (el menú de la cabecera de la ejecución).

La ejecuciónAl final de vitest
Creada por el reporterSe cierra, una vez enviados todos los resultados y archivos
Reutilizada (run.ulid)Queda abierta: la cierra quien la creó
Creada en una sesión watch (vitest --watch)Queda abierta: cada nueva ejecución de la sesión reporta en ella
Cualquiera, si un informe falló tras los reintentosQueda abierta: el registro la nombra, y el error dice qué hacer

closeRun (PROBARA_CLOSE_RUN) decide para cada ejecución de un comando que no sea una sesión watch: true cierra también una ejecución reutilizada, false deja abierta una creada. closeRuns decide por proyecto ({ SHOP: true, WEB: false }) cuando closeRun no está definido. Cuando un informe falla, lo que no se envió puede ir a un archivo de resultados, que probara import results envía más tarde a la misma ejecución, y la cierra como lo habría hecho el reporter.

  • Modo watch. vitest --watch (y vitest a secas en una terminal, que inicia el modo watch) crea una ejecución por proyecto de Probara para toda la sesión: cada nueva ejecución de las pruebas reporta en ella, y la línea Sending cuenta solo esa nueva ejecución. El reporter nunca la cierra, y dice una vez cómo hacerlo. Una ejecución cerrada o eliminada en Probara durante la sesión no recibe más resultados: el reporter envía los resultados de esa nueva ejecución a una ejecución nueva (o los guarda en el archivo de resultados, si hay uno definido), y lo indica (modo watch).
  • Shards con el reporter blob. Un shard (vitest run --shard=1/2) que escribe un blob no envía nada ni crea ninguna ejecución: vitest --merge-reports reporta los resultados de todos los shards en una sola ejecución, que cierra. Un shard con el reporter junto a blob en sus reporters lo indica: Sharded run with the blob reporter: the results are reported by vitest --merge-reports (sharding).

Cierra una ejecución a mano con la CLI de Probara:

Ventana de terminal
npx @probara/cli run close --run-ulid 01J9Z3K4M5N6P7Q8R9S0T1V2W3

Con varios proyectos de Probara, cada proyecto tiene su propia ejecución. El nombre, la descripción, el entorno (por nombre) y las etiquetas van con cada ejecución nueva; el hito, el plan y las configuraciones van solo con la ejecución del proyecto configurado.

Cada intento se envía con el veredicto del propio Vitest, como passed, failed o skipped. statusMapping y statusFilter pueden cambiarlo después.

El intentoEstado
Aprobadopassed
Fallido: una aserción, un error, un tiempo agotado, un beforeEach o afterEach que lanzó un errorfailed
Fallos de expect.softfailed, con cada fallo en las notas
test.skip, skipIf, runIf, un describe omitido, una prueba que .only o -t dejan fueraskipped
test.todoskipped, con la nota Todo
context.skip(); con una nota, context.skip('why')skipped; con una nota, la nota Skipped: why
test.fails, y lanzó el error esperadopassed
test.fails, pero pasófailed, con el error de Vitest Expect test to fail
Una prueba bajo un beforeAll que lanzó un errorskipped
Una prueba que Vitest nunca inició, después de --bail o Ctrl-Cskipped, con la nota Not run: the test run was interrupted

El reporter nunca envía blocked por sí solo: mapea un estado a él (abajo) cuando lo necesites.

tests/statuses.test.ts
import { expect, test } from 'vitest';
test('passes', () => {});
test('fails', () => {
expect(1 + 1).toBe(3);
});
test.skip('is skipped', () => {});
test.todo('is not written yet');
test('skips itself', (context) => {
context.skip('needs the payment sandbox');
});
test.fails('is a known bug', () => {
expect(0.1 + 0.2).toBe(0.3);
});
[
{ "automationKey": "tests/statuses.test.ts > passes", "status": "passed" },
{ "automationKey": "tests/statuses.test.ts > fails", "status": "failed" },
{ "automationKey": "tests/statuses.test.ts > is skipped", "status": "skipped" },
{
"automationKey": "tests/statuses.test.ts > is not written yet",
"status": "skipped",
"notes": "Todo"
},
{
"automationKey": "tests/statuses.test.ts > skips itself",
"status": "skipped",
"notes": "Skipped: needs the payment sandbox"
},
{ "automationKey": "tests/statuses.test.ts > is a known bug", "status": "passed" }
]
  • Orden. Los resultados se envían archivo por archivo cuando termina la ejecución, las pruebas de cada archivo en el orden en que están escritas, y cada intento de una prueba en el orden en que se ejecutó.
  • Los errores van a las notas del resultado: cada error del intento, incluidos los fallos de expect.soft, en orden, cada uno con su mensaje y su traza, sin los colores de la terminal, después de un comentario si la prueba escribió uno. Un intento aprobado no envía ningún error.
  • Las omisiones no se distinguen. Vitest reporta test.skip, skipIf, runIf, .only y -t del mismo modo, igual que su salida JUnit: son resultados omitidos sin nota, como los registra probara import junit.
  • Las pruebas todo nunca se pierden: son resultados omitidos con la nota Todo, así que el caso muestra lo que queda por escribir.
  • Los fallos esperados son los de Vitest: una prueba test.fails que lanza un error hace lo que debe, así que pasa. Cuando se corrige el fallo, la prueba pasa, Vitest la hace fallar, y Probara también, lo que te recuerda quitar .fails.
  • Una ejecución interrumpida (--bail, Ctrl-C) reporta igualmente lo que ejecutó. Una prueba que Vitest nunca inició se omite con la nota Not run: the test run was interrupted; una prueba que el propio Vitest omitió porque la ejecución se canceló conserva la nota de Vitest, The test run was aborted by the user. Un archivo de prueba que Vitest nunca inició no tiene ninguna prueba que reportar: una advertencia cuenta esos archivos.

Un error en un hook de una suite o en el propio archivo hace fallar el archivo en Vitest, aunque sus pruebas pasen. El reporter envía los resultados fallidos que la salida JUnit de Vitest escribe para él, con el error en sus notas, así que Probara tampoco muestra el archivo en verde:

Dónde ocurre el errorQué recibe Probara
El beforeAll o afterAll de un describeUn resultado fallido con el nombre del describe: tests/session.test.ts > session
Un beforeAll o afterAll fuera de todo describeUn resultado fallido con el nombre del archivo: tests/cleanup.test.ts > tests/cleanup.test.ts
El archivo de prueba no carga (un error de sintaxis, una importación que lanza un error)Un resultado fallido con el nombre del archivo: tests/broken.test.ts > tests/broken.test.ts
Un error no gestionado: un rechazo que ninguna prueba esperó, un error lanzado desde un temporizadorNingún resultado: Vitest lo lista entre sus errores no gestionados, y una advertencia los cuenta
tests/session.test.ts
import { beforeAll, describe, test } from 'vitest';
describe('session', () => {
beforeAll(() => {
throw new Error('Could not seed the users');
});
test('renews the token', () => {});
});
test('logs out', () => {});
[
{ "automationKey": "tests/session.test.ts > session", "status": "failed" },
{ "automationKey": "tests/session.test.ts > session > renews the token", "status": "skipped" },
{ "automationKey": "tests/session.test.ts > logs out", "status": "passed" }
]

Los resultados fallidos van primero en su archivo. Sus claves son las que probara import junit da a los mismos fallos en la salida JUnit de Vitest, así que ambas herramientas los registran en el mismo caso, con nombres raros incluidos: el escritor JUnit de Vitest nombra el fallo de un hook con su propio describe, no con los bloques describe que tiene por encima, y el fallo de un archivo con el archivo, que su clave contiene entonces dos veces.

Un archivo que no carga es un resultado fallido, contenga las pruebas que contenga:

tests/broken.test.ts
import { expect, test } from 'vitest';
import { total } from './missing-module';
test('adds the items', () => {
expect(total([1, 2])).toBe(3);
});
[
{
"automationKey": "tests/broken.test.ts > tests/broken.test.ts",
"status": "failed"
}
]

Corrige el archivo: la propia salida de Vitest muestra el error completo.

statusMapping envía un estado como otro; statusFilter no envía ningún resultado con los estados indicados, después del mapeo. Ambos aceptan passed, failed, skipped y blocked:

reporters: [
'default',
[
'@probara/vitest-reporter',
{ statusMapping: { failed: 'blocked' }, statusFilter: ['skipped'] },
],
],
tests/filters.test.ts
import { expect, test } from 'vitest';
test('passes', () => {});
test('fails', () => {
expect(true).toBe(false);
});
test.todo('is not written yet');
$ npx vitest run
[probara] Sending 2 results of 2 tests (1 passed, 0 failed, 0 skipped, 1 blocked); 1 left out by statusFilter
[probara] Recorded 2 results (2 new cases, 0 unmatched) in R-1 (closed): https://app.probara.net/projects/SHOP/runs/R-1
[probara] Filtered out 1 result by their status (statusFilter): not sent

Como variables: PROBARA_STATUS_MAPPING=failed=blocked,skipped=passed y PROBARA_STATUS_FILTER=skipped,blocked. Un valor que no es un estado, o un estado mapeado dos veces, es un problema de configuración que desactiva el envío. statusFilter: ['skipped'] deja fuera también las pruebas todo: son resultados omitidos. El mapeo solo cambia lo que registra Probara: el código de salida de Vitest sigue siendo el de las pruebas.

Cada ejecución de una prueba es un resultado propio: cada intento que le da el retry de Vitest, y cada vez que repeats la vuelve a ejecutar. Una prueba reintentada una vez envía dos resultados, en el orden en que se ejecutaron, cada uno con su propio estado, su duración, sus errores, sus pasos y sus archivos.

tests/dashboard.test.ts
import { expect, test } from 'vitest';
let loads = 0;
test('loads the dashboard', { retry: 1 }, () => {
loads += 1;
// Fails the first time, passes on the retry.
expect(loads).toBe(2);
});
test('opens the menu', { repeats: 2 }, () => {});
[
{ "automationKey": "tests/dashboard.test.ts > loads the dashboard", "status": "failed" },
{
"automationKey": "tests/dashboard.test.ts > loads the dashboard",
"status": "passed",
"parameters": { "attempt": "2" }
},
{ "automationKey": "tests/dashboard.test.ts > opens the menu", "status": "passed" },
{
"automationKey": "tests/dashboard.test.ts > opens the menu",
"status": "passed",
"parameters": { "repeat": "2" }
},
{
"automationKey": "tests/dashboard.test.ts > opens the menu",
"status": "passed",
"parameters": { "repeat": "3" }
}
]
$ npx vitest run
[probara] Sending 5 results of 2 tests (4 passed, 1 failed, 0 skipped, 0 blocked)
[probara] Recorded 5 results (2 new cases, 0 unmatched) in R-1 (closed): https://app.probara.net/projects/SHOP/runs/R-1
  • Qué muestra Probara. El caso de la ejecución conserva el resultado de la última ejecución (passed, aquí), y cada ejecución queda en su historial: una prueba inestable es un caso cuyo historial mezcla fallos y aprobados en la misma ejecución. El recuento del registro lo indica: más resultados que pruebas.
  • Los parámetros distinguen las ejecuciones. attempt vale 2, 3… a partir del segundo intento, y repeat vale 2, 3… a partir de la segunda ejecución de repeats. Cada repetición reintenta por su cuenta, así que sus intentos vuelven a empezar en 1: el segundo intento de la segunda repetición tiene { "repeat": "2", "attempt": "2" }. Ganan a los probara.parameters() con el mismo nombre, y nunca forman parte de la clave: cada ejecución va al mismo caso.
  • Cada intento empieza vacío. Las llamadas probara.*, los pasos, los archivos y la salida de consola pertenecen al intento que los produjo, así que un reintento no hereda lo que registró el primer intento.
  • Errores por intento. Las notas de un intento fallido contienen solo sus propios errores, no los de los intentos anteriores.
  • Sin marca de inestable. El reporter no marca los intentos como inestables: los propios intentos son la prueba. La salida JUnit de Vitest, y por tanto probara import junit, tiene un resultado por prueba, por muchos intentos que haya necesitado.

repeats: 2 ejecuta una prueba tres veces: una, y después dos más. Vitest hace fallar una prueba así cuando falló cualquiera de sus ejecuciones; Probara recibe cada ejecución con su propio estado, y ningún resultado adicional para el veredicto de Vitest, que contaría un fallo dos veces. Así, una prueba repetida cuya última ejecución pasó muestra passed en la ejecución aunque Vitest la hiciera fallar: sus ejecuciones fallidas están en el historial del caso.

Vitest reintenta una prueba fallida en ese momento, antes de la siguiente prueba, con sus hooks beforeEach y afterEach alrededor de cada intento. Sea lo que sea lo que define los reintentos (el retry de la configuración, de un describe o de una prueba, o --retry) y sea cual sea su condición o su espera, cada intento es un resultado.

VitestQué recibe Probara
retry, --retryUn resultado por intento
repeatsUn resultado por ejecución, y por intento de cada ejecución
test.failsUn resultado: Vitest nunca reintenta una prueba test.fails
test.concurrent con retryUn resultado por intento, cada uno con sus propios errores
Un shard ejecutado con --reporter=blob soloSolo el intento final, con una advertencia en la fusión (abajo)

Los intentos los registra el archivo de setup que el reporter añade a cada proyecto de Vitest. Donde no se ejecuta, Vitest sigue reintentando, pero solo se puede enviar el intento final de cada prueba, y una advertencia dice cuántas pruebas fueron: Vitest retried or repeated 1 test whose earlier attempts were not recorded: only its final attempt is reported. Eso ocurre cuando Vitest se ejecuta sin el reporter entre sus reporters, como un shard ejecutado con --reporter=blob solo en la línea de comandos, que sustituye los reporters de la configuración: nombra el reporter junto a él, --reporter=blob --reporter=@probara/vitest-reporter (el reporter va junto a blob).

Para enviar solo el último intento, no reintentes en Vitest: ninguna opción del reporter descarta intentos. Para que los fallos de las pruebas reintentadas no cuenten, mapéalos (mapeo de estados), teniendo en cuenta que se aplica a todos los fallos.

Cuando un informe no se puede enviar (Probara inalcanzable, la red caída, un informe rechazado), sus resultados se pierden salvo que los guardes. Define un archivo de resultados, y el reporter escribe en él lo que no pudo enviar al final de la ejecución; probara import results lo envía más tarde, a las mismas ejecuciones.

reporters: ['default', ['@probara/vitest-reporter', { resultsFile: 'probara-results.json' }]],

O PROBARA_RESULTS_FILE=probara-results.json, relativo al directorio en el que se ejecuta vitest.

$ PROBARA_RESULTS_FILE=probara-results.json npx vitest run
[probara] Sending 3 results of 3 tests (3 passed, 0 failed, 0 skipped, 0 blocked)
[probara] 3 results were not sent: Probara answered 403 forbidden: <message from Probara>. No run was created or updated
[probara] Wrote the 3 results that were not sent to /work/shop/probara-results.json: send them with probara import results /work/shop/probara-results.json

Después, desde cualquier job que tenga el token, envía lo que quedó pendiente:

Ventana de terminal
npx @probara/cli import results 'probara-results*.json'

Pon el patrón entre comillas: lo expande probara, y coincide con el archivo y con los hermanos que se describen abajo. Si no coincide nada, no quedó nada sin enviar: la importación lo indica y sale con 0.

  • Solo cuando hace falta. El archivo solo se escribe cuando algo no se envió: si todos los resultados llegaron, no hay archivo.
  • A las mismas ejecuciones. El archivo nombra las ejecuciones a las que pertenecen sus resultados: una ejecución que el informe fallido dejó abierta recibe el resto de sus resultados, y una ejecución que nunca se creó la crea la importación con el mismo nombre y los mismos ajustes. Las ejecuciones se cierran como las habría cerrado el reporter.
  • La importación lo consume. probara import results envía cada archivo por separado, y después lo elimina (junto con su carpeta <name>-attachments/) cuando se enviaron todos sus resultados, o lo reescribe solo con lo que sigue sin enviarse. Importar de nuevo nunca envía un resultado dos veces, así que la importación es segura en cualquier pipeline. --dry-run nunca toca los archivos.
  • Nunca toca un archivo anterior. Si ya hay un archivo en esa ruta (el de otro shard en un disco compartido, o el de una ejecución anterior), el reporter lo deja como está y escribe en el primer hermano libre: probara-results-2.json, después -3, y así sucesivamente, cada uno con su propia carpeta de adjuntos. El registro nombra el archivo escrito, y el patrón los importa todos, del más antiguo al más reciente.
  • Nunca a medio escribir. Cada archivo se escribe completo primero en un archivo temporal de la misma carpeta (con un nombre que empieza por punto, que el patrón nunca encuentra), y después aparece de golpe con su nombre: una importación que se ejecuta a la vez ve el archivo completo o no lo ve.

Una segunda ejecución que no puede enviar mientras sigue ahí el archivo de la primera:

$ PROBARA_RESULTS_FILE=probara-results.json npx vitest run
[probara] Sending 3 results of 3 tests (3 passed, 0 failed, 0 skipped, 0 blocked)
[probara] 3 results were not sent: Probara answered 403 forbidden: <message from Probara>. No run was created or updated
[probara] Wrote the 3 results that were not sent to /work/shop/probara-results.json: send them with probara import results /work/shop/probara-results.json
$ PROBARA_RESULTS_FILE=probara-results.json npx vitest run
[probara] Sending 3 results of 3 tests (3 passed, 0 failed, 0 skipped, 0 blocked)
[probara] 3 results were not sent: Probara answered 403 forbidden: <message from Probara>. No run was created or updated
[probara] Wrote the 3 results that were not sent to /work/shop/probara-results-2.json (/work/shop/probara-results.json already exists): send them with probara import results /work/shop/probara-results-2.json

Cada archivo que lleva un resultado se copia junto al archivo de resultados, en su carpeta <name>-attachments/ (probara-results-attachments/), y el archivo los nombra de forma relativa a sí mismo: lo que copió probara.attach(), los archivos del context.annotate() de Vitest, las capturas de pantalla de los fallos de las pruebas de navegador y la salida de consola de captureOutput. El archivo nunca apunta al attachmentsDir de Vitest, que una ejecución posterior o un paso de limpieza pueden vaciar. Mueve o descarga juntos el archivo y su carpeta, a cualquier lugar, e impórtalo desde ahí: un artefacto de CI que descarga otro job conserva sus adjuntos.

tests/receipt.test.ts
import { probara } from '@probara/vitest-reporter';
import { test } from 'vitest';
test('prints the receipt', async () => {
await probara.attach({ name: 'receipt', body: 'Total: 25.00' });
});
$ PROBARA_ENABLED=false PROBARA_RESULTS_FILE=probara-results.json npx vitest run
[probara] Wrote 1 result 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
[probara] probara-results.json: 1 result
[probara] Results: 1 (1 passed, 0 failed, 0 skipped, 0 blocked)
[probara] Project: SHOP
[probara] Run: new run "Automated run 2026-09-29 14:05 UTC"
[probara] Base URL: https://app.probara.net
[probara] Missing cases: created
[probara] Attachments: on
[probara] Recorded 1 result (1 new case, 0 unmatched) in R-1 (closed): https://app.probara.net/projects/SHOP/runs/R-1
[probara] Attached 1 file to results (0 skipped, 0 failed)
[probara] Deleted probara-results.json and probara-results-attachments: every result was sent

Una subida que falla durante la importación no se guarda para otro intento: su resultado ya se registró, así que ya no está en el archivo, y la carpeta se va con el archivo cuando se enviaron todos los resultados. La importación lo registra y sale con 1.

Con el envío desactivado (PROBARA_ENABLED=false, o sin token), el reporter escribe cada intento en el archivo, vínculos con casos incluidos. Ejecuta las pruebas donde no hay token (un fork, una máquina sin red), e importa el archivo desde un job que lo tenga:

$ PROBARA_ENABLED=false 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

El mismo archivo muestra lo que se enviaría sin enviarlo: consulta comprobar qué se enviaría.

Guarda los archivos y sus carpetas <name>-attachments/ como artefactos del job de pruebas, e impórtalos en un job (o paso) posterior que tenga el token:

- name: Run Vitest tests
run: npx vitest run
env:
PROBARA_API_TOKEN: ${{ secrets.PROBARA_API_TOKEN }}
PROBARA_RESULTS_FILE: probara-results.json
- name: Send what Probara did not get
if: always()
run: npx @probara/cli import results 'probara-results*.json'
env:
PROBARA_API_TOKEN: ${{ secrets.PROBARA_API_TOKEN }}

Un paso posterior en el mismo job también sirve, como arriba: si Probara solo estuvo caído un momento, la importación envía el resto. Si sigue sin poder, la importación sale con 1 y guarda en cada archivo lo que no pudo enviar; los archivos que envió desaparecen.

Un archivo de resultados es una entrada de confianza: sus adjuntos se suben desde las rutas que nombra, así que importa solo los archivos que escribieron tus propios jobs. La importación deja fuera, con una advertencia, un adjunto cuya ruta relativa sale de la carpeta del archivo; las rutas absolutas se conservan.

Una nueva ejecución de una sesión watch que se rechaza porque su ejecución se cerró también se guarda en el archivo, nombrando esa ejecución, y el registro dice cómo enviarla a una ejecución abierta con --run-ulid (cuando se cierra la ejecución durante la sesión).

La versión 1 de un documento JSON: el proyecto, las ejecuciones y los ajustes del reporter (nunca el token), y después cada resultado tal como lo construyó el reporter, antes de statusMapping (que se aplica cuando se envía el archivo). El formato completo está en el archivo de resultados de core, y la importación (varios archivos y patrones, el resumen JSON, los códigos de salida) se describe en probara import results.

assignFailedTo nombra a las personas que investigan los fallos. Cada informe pide a Probara que asigne cada caso de la ejecución que deja fallido, y que todavía no tiene responsable, a una de ellas, por turnos, para que una ejecución nocturna con fallos llegue a la lista de alguien sin que nadie tenga que clasificarla antes.

reporters: [
'default',
[
'@probara/vitest-reporter',
{ assignFailedTo: ['ana@example.com', 'bo@example.com', 'cy@example.com'] },
],
],
tests/checkout.test.ts
import { expect, test } from 'vitest';
test('pays with a card', () => {
expect('declined').toBe('paid');
});
test('pays with a voucher', () => {
expect(0).toBe(25);
});
test('shows the total', () => {});

Con ana@example.com y bo@example.com como miembros del proyecto y cy@example.com no, los dos casos fallidos van a Ana y a Bo, y Probara indica que un email no coincidió con nadie:

$ npx vitest run
[probara] Sending 3 results of 3 tests (1 passed, 2 failed, 0 skipped, 0 blocked)
[probara] Probara warned: assignFailedTo: 1 of 3 emails did not match a member who can be assigned in this project
[probara] Recorded 3 results (3 new cases, 0 unmatched) in R-1 (closed): https://app.probara.net/projects/SHOP/runs/R-1

O desde el entorno: PROBARA_ASSIGN_FAILED_TO=ana@example.com,bo@example.com.

ReglaPor qué
Solo los casos de la ejecución que un informe deja en failedLos resultados aprobados, omitidos y bloqueados no necesitan a nadie
Solo los casos de la ejecución sin responsableUn responsable existente nunca se sustituye: alguien ya se ocupa de él
Solo miembros activos que pueden ejecutar pruebas en el proyectoUn caso no se puede asignar a alguien que no puede trabajar en él
Los miembros de la lista se turnan, en el orden en que los listasLos fallos se reparten, no se acumulan en el primer nombre
Un email que no coincide con ningún miembro así se omiteLos resultados se registran igualmente; la advertencia de Probara los cuenta
  • Decide el último intento. Una prueba reintentada que falló y después pasó deja su caso de la ejecución aprobado, así que no se asigna nada; cada intento fallido sigue siendo un resultado del caso.
  • Después de statusMapping. El estado que cuenta es el que registra Probara: con statusMapping: { failed: 'blocked' }, nada queda fallido, así que no se asigna nada.
  • La advertencia nunca nombra los emails, solo cuántos se omitieron: el registro de un job de CI no es el lugar para listar quién es miembro y quién no. Compara la lista con los miembros del proyecto en Probara.
  • Los turnos vuelven a empezar con cada informe: cada informe (un bloque de hasta 500 resultados, un shard, una nueva ejecución en modo watch) da su primer caso fallido al primer miembro de la lista.
  • Cada informe de la ejecución lo pide, con la misma lista: una ejecución con varios proyectos de Probara lo pide en la ejecución de cada proyecto, y los shards de una ejecución compartida asignan cada uno los casos que dejan fallidos.
  • Un archivo de resultados conserva la lista. probara import results la envía con los resultados, salvo que --assign-failed-to o PROBARA_ASSIGN_FAILED_TO nombren a otras personas.

Relacionado: Configuración · Sharding y proyectos · Solución de problemas · Fuente: runs.md, statuses.md, retries.md, results-file.md, assign-failed.md