Sharding de Vitest y proyectos de Vitest
Fuera de GitHub Actions, cada vitest run --shard crea su propia ejecución salvo que los shards estén
vinculados entre sí. En GitHub Actions los shards de un mismo workflow comparten una ejecución
automáticamente (jobs en paralelo).
En otros entornos, esta página muestra las dos formas de obtener una sola ejecución para todo un pipeline, cómo se
comportan los projects del propio Vitest, y cómo una batería de pruebas reporta en varios
proyectos de Probara.
Los workers de un mismo vitest run no necesitan nada: todos reportan a través del único reporter
del proceso principal de Vitest, en una sola ejecución.
Una ejecución para todos los shards
Sección titulada «Una ejecución para todos los shards»| Patrón | Elígelo cuando |
|---|---|
| 1. Fusionar los informes blob | La forma habitual, y la del propio Vitest: un job reporta todos los shards, y los shards no necesitan token |
| 2. Crear la ejecución, reportar desde cada shard y cerrarla | Los resultados de cada shard deben llegar a Probara en cuanto termina, runCasesOnly debe aplicarse, o ningún job puede fusionar en la ruta de los shards |
Los jobs que reportan necesitan PROBARA_API_TOKEN, un token de aplicación de la tarjeta Vitest
en Workspace › Integraciones, configurado como en la
sección de tu proveedor de CI.
Patrón 1: fusionar los informes blob
Sección titulada «Patrón 1: fusionar los informes blob»Cada shard escribe un informe blob de Vitest, con el reporter junto al reporter blob, y un job
fusiona los blobs: vitest --merge-reports reporta cada intento de cada shard, con sus pasos y sus
archivos, en una sola ejecución, y la cierra.
- Cada shard se ejecuta con los dos reporters en su línea de comandos.
--reportersustituye los reporters de la configuración, así que nombra este junto ablob:npx vitest run --shard=1/4 --reporter=blob --reporter=@probara/vitest-reporter. El shard escribe su blob, conserva los archivos que adjuntaron sus pruebas, no envía nada, y lo indica. No necesita token, ni ninguna de las opciones del reporter: la fusión reporta con las de la configuración. - Copia los blobs y los adjuntos de cada shard al job que fusiona, en la misma ruta que en los shards (abajo).
- Ese job ejecuta
npx vitest --merge-reportscon el token: el reporter de la configuración envía los resultados de todos los shards a una sola ejecución.
En una sola terminal, el flujo completo es:
$ npx vitest run --shard=1/2 --reporter=blob --reporter=@probara/vitest-reporter[probara] Sharded run with the blob reporter: the results are reported by vitest --merge-reports$ npx vitest run --shard=2/2 --reporter=blob --reporter=@probara/vitest-reporter[probara] Sharded run with the blob reporter: the results are reported by vitest --merge-reports$ npx vitest --merge-reports[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 (closed): https://app.probara.net/projects/SHOP/runs/R-1Los workflows completos están en las secciones de GitHub Actions y de GitLab CI de Proveedores de CI.
El reporter va junto a blob
Sección titulada «El reporter va junto a blob»| Los shards se ejecutan con | Qué envía la fusión |
|---|---|
--reporter=blob --reporter=@probara/vitest-reporter | Cada intento, las llamadas probara.* y sus archivos |
--reporter=blob solo | Solo el intento final de una prueba reintentada (una advertencia dice cuántas), y ninguna llamada probara.*: el reporter nunca se ejecutó en los shards (cuándo se ejecutan los reintentos) |
Deja blob fuera de la configuración que lee vitest --merge-reports: Vitest se niega a fusionar
con él (Cannot merge reports when `--reporter=blob` is used).
Lleva los blobs y los adjuntos
Sección titulada «Lleva los blobs y los adjuntos»| Qué | Vitest 3 y 4 | Vitest 5 |
|---|---|---|
Los blobs, que lee vitest --merge-reports | .vitest-reports/ | .vitest/blob/ |
attachmentsDir: los archivos que adjuntaron las pruebas | .vitest-attachments/ | .vitest/attachments/ |
Guarda las dos carpetas de cada shard como artefactos, y descárgalas todas en las mismas carpetas
del job que fusiona: cada blob tiene un nombre propio (blob-1-4.json), y también cada copia de un
archivo adjunto. Un archivo que la fusión no encuentra se omite, con la advertencia
Skipped an attachment: its file is missing or unreadable, y su resultado se envía igualmente
(dónde se guardan las copias).
Fusiona en la misma ruta
Sección titulada «Fusiona en la misma ruta»Un blob nombra cada archivo de prueba, y cada archivo adjunto, por su ruta completa en el shard, y
una clave de automatización empieza con la ruta del archivo de prueba desde la raíz de la ejecución
que fusiona. Si se fusiona en otra ruta, todas las claves cambian, y todas las pruebas reciben un
caso nuevo. Ejecuta la fusión en un checkout en la misma ruta que los shards. Los registros lo
muestran: la raíz que nombra la línea RUN de la fusión debe ser la carpeta que contiene la carpeta
.vitest (.vitest-reports en Vitest 3 y 4) de la línea blob report written to de cada shard.
La misma versión de Vitest en todas partes
Sección titulada «La misma versión de Vitest en todas partes»vitest --merge-reports solo lee los blobs de su propia versión de Vitest, y falla con cualquier
otra. Instala desde el lockfile en cada job (npm ci), y actualiza a la vez los shards y el job que
fusiona
(cualquier actualización de un pipeline con sharding).
Selección de pruebas
Sección titulada «Selección de pruebas»runCasesOnly no se aplica a los shards que escriben un blob: cada shard advierte
(runCasesOnly does not apply to a sharded run with the blob reporter: every test runs, and vitest --merge-reports reports them all),
ejecuta todas las pruebas, y la fusión las reporta todas. Para ejecutar en shards solo las pruebas
de una ejecución de Probara, usa el patrón 2
(selección de pruebas).
Patrón 2: crea la ejecución, reporta desde cada shard y ciérrala
Sección titulada «Patrón 2: crea la ejecución, reporta desde cada shard y ciérrala»- Un primer job ejecuta
probara run create, que crea una ejecución automatizada vacía e imprime su ULID en stdout. - Cada shard ejecuta
npx vitest run --shard=<i>/<n>con ese ULID enPROBARA_RUN_ULID, y envía sus resultados al terminar. Un shard nunca cierra una ejecución que no creó, así que todos reportan en la ejecución abierta. Probara concilia los shards que reportan en el mismo momento: ningún caso se añade dos veces a la ejecución. - Un último job ejecuta
probara run close, después de todos los shards, incluso si algún shard falló.
En una terminal, el flujo completo es:
PROBARA_RUN_ULID=$(npx @probara/cli run create)export PROBARA_RUN_ULIDnpx vitest run --shard=1/2npx vitest run --shard=2/2npx @probara/cli run closeAsigna el ULID en su propia línea: export PROBARA_RUN_ULID=$(...) ocultaría una creación fallida.
probara es la CLI de Probara; usa el mismo token y el mismo proyecto. Las
opciones de una ejecución nueva van en run create (--run-name, --environment, --milestone,
--plan, --tag…): los shards reutilizan la ejecución, e ignoran sus propias opciones de
ejecución con una advertencia
(una ejecución existente).
Con runCasesOnly, cada shard lee los casos de la ejecución, y ejecuta solo las pruebas suyas que
pertenecen a la ejecución
(selección de pruebas).
GitHub Actions
Sección titulada «GitHub Actions»jobs: probara-run: runs-on: ubuntu-latest outputs: ulid: ${{ steps.create.outputs.ulid }} env: PROBARA_API_TOKEN: ${{ secrets.PROBARA_API_TOKEN }} PROBARA_PROJECT: SHOP # Fork pull requests get no secrets: report nothing there. PROBARA_ENABLED: ${{ secrets.PROBARA_API_TOKEN != '' }} steps: - uses: actions/setup-node@v5 with: node-version: 22 - id: create run: | ulid=$(npx @probara/cli run create) echo "ulid=$ulid" >> "$GITHUB_OUTPUT"
test: needs: probara-run runs-on: ubuntu-latest strategy: fail-fast: false matrix: shardIndex: [1, 2, 3, 4] shardTotal: [4] steps: - uses: actions/checkout@v5 - uses: actions/setup-node@v5 with: node-version: 22 - run: npm ci - run: npx vitest run --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} env: PROBARA_API_TOKEN: ${{ secrets.PROBARA_API_TOKEN }} PROBARA_PROJECT: SHOP PROBARA_ENABLED: ${{ secrets.PROBARA_API_TOKEN != '' }} PROBARA_RUN_ULID: ${{ needs.probara-run.outputs.ulid }}
close-probara-run: needs: [probara-run, test] if: always() && needs.probara-run.outputs.ulid != '' runs-on: ubuntu-latest steps: - uses: actions/setup-node@v5 with: node-version: 22 - run: npx @probara/cli run close env: PROBARA_API_TOKEN: ${{ secrets.PROBARA_API_TOKEN }} PROBARA_PROJECT: SHOP PROBARA_RUN_ULID: ${{ needs.probara-run.outputs.ulid }}Sin el token (un fork), PROBARA_ENABLED vale false: run create no imprime nada y sale con 0,
los shards no reportan nada, y el job de cierre se omite.
GitLab CI
Sección titulada «GitLab CI»Un artefacto dotenv pasa el ULID a cada job posterior:
stages: - test
create-probara-run: stage: .pre image: node:22 variables: PROBARA_PROJECT: SHOP rules: - if: $PROBARA_API_TOKEN script: - PROBARA_RUN_ULID=$(npx @probara/cli run create) - echo "PROBARA_RUN_ULID=$PROBARA_RUN_ULID" > probara.env artifacts: reports: dotenv: probara.env
vitest: stage: test image: node:22 parallel: 4 variables: PROBARA_PROJECT: SHOP script: - npm ci - npx vitest run --shard=$CI_NODE_INDEX/$CI_NODE_TOTAL
close-probara-run: stage: .post image: node:22 variables: PROBARA_PROJECT: SHOP rules: - if: $PROBARA_API_TOKEN when: always script: - npx @probara/cli run close.pre y .post son la primera y la última etapa integradas de GitLab; when: always cierra la
ejecución incluso después de shards fallidos. Un pipeline sin la variable (el de un fork) no tiene
ninguno de los dos jobs, y sus shards no reportan nada.
Otros proveedores de CI
Sección titulada «Otros proveedores de CI»Proveedores de CI muestra los mismos tres pasos para CircleCI, Jenkins, Azure Pipelines, Bitbucket Pipelines y Buildkite. El patrón 1 también funciona en ellos cuando el job que fusiona recibe las carpetas de cada shard en la ruta de los shards, y se ejecuta después de shards fallidos: Bitbucket omite los pasos posteriores a uno fallido.
Si el cierre nunca se ejecutó
Sección titulada «Si el cierre nunca se ejecutó»Una ejecución queda abierta hasta que se cierra. Ciérrala a mano, con el ULID del registro del job de creación:
npx @probara/cli run close --run-ulid 01J9Z3K4M5N6P7Q8R9S0T1V2W3Qué patrón pierde menos
Sección titulada «Qué patrón pierde menos»| Algo sale mal | Patrón 1 (fusión) | Patrón 2 (ejecución compartida) |
|---|---|---|
| Un shard muere antes de que termine Vitest | Falta su blob: los demás shards se reportan | No envía nada: los demás shards se reportan |
| Probara es inalcanzable | El archivo de resultados del job que fusiona guarda lo que no pudo enviar (si está definido) | El archivo de resultados de cada shard guarda lo que no pudo enviar (si está definido) |
| El job de cierre no se ejecuta | No hay nada que cerrar: la fusión cierra su propia ejecución | La ejecución queda abierta: ciérrala a mano |
En ambos, el código de salida de cada job sigue siendo el de las pruebas: un problema al reportar nunca hace fallar un shard ni la fusión.
Proyectos de Vitest
Sección titulada «Proyectos de Vitest»Aquí se llaman proyectos dos cosas distintas. Los
projects de Vitest dividen un comando vitest en varias
configuraciones (por ejemplo, una unit y una smoke); la opción projects del reporter permite
que una batería de pruebas reporte en varios proyectos de Probara.
Cada una funciona por su cuenta.
Registra el reporter una sola vez, en la configuración raíz, junto a projects: Vitest ejecuta un
único conjunto de reporters para todos sus proyectos, y el reporter envía las pruebas de todos los
proyectos a una sola ejecución de Probara. Añade él mismo su archivo de setup y su runner a cada
proyecto.
// vitest.config.mtsimport { defineConfig } from 'vitest/config';
export default defineConfig({ test: { reporters: ['default', ['@probara/vitest-reporter', { projectId: 'SHOP' }]], projects: [ { test: { name: 'unit', include: ['tests/**/*.test.ts'] } }, { test: { name: 'smoke', include: ['tests/cart.test.ts'] } }, ], },});import { probara } from '@probara/vitest-reporter';import { test } from 'vitest';
test('adds an item', () => { probara.parameters({ currency: 'EUR' });});import { test } from 'vitest';
test('lists the orders', () => {});[ { "automationKey": "tests/cart.test.ts > adds an item", "parameters": { "project": "unit", "currency": "EUR" } }, { "automationKey": "tests/orders.test.ts > lists the orders", "parameters": { "project": "unit" } }, { "automationKey": "tests/cart.test.ts > adds an item", "parameters": { "project": "smoke", "currency": "EUR" } }]- Las claves no tienen proyecto. Como en la salida JUnit de Vitest, un proyecto de Vitest no añade nada a la clave de automatización: el archivo (relativo a la raíz de Vitest), y después los nombres. Mover pruebas entre proyectos de Vitest conserva sus casos.
- Un archivo que ejecutan dos proyectos (sus
includese solapan, comotests/cart.test.tsarriba) se reporta una vez por proyecto, con la misma clave: dos resultados de un caso, como dos reintentos. - El parámetro
projectnombra el proyecto de Vitest de cada resultado cuando la configuración tiene más de uno. Una configuración con un solo proyecto, o con ninguno, no envía parámetroproject. Unprojectque definas conprobara.parameters()gana al de Vitest;attemptyrepeatganan a ambos. - La ejecución de un archivo en cada proyecto es una prueba propia: sus intentos, sus llamadas
probara.*y sus archivos se quedan con el resultado de ese proyecto, como muestracurrencyarriba. - Nada que añadir por proyecto. El reporter pone su archivo de setup el primero en los
setupFilesde cada proyecto (tus propios archivos de setup mantienen su orden) y envuelve elrunnerde cada proyecto, así que los reintentos, la selección de pruebas y los helpers funcionan en todos los proyectos. Un proyecto de navegador recibe en su lugar el archivo de setup para navegador (modo navegador).
Varios proyectos de Probara
Sección titulada «Varios proyectos de Probara»Una batería de Vitest puede contener las pruebas de varios proyectos de Probara: una batería
compartida cuyos casos están en SHOP, WEB y API. Lista los otros proyectos en projects, y
cada resultado va al proyecto de su caso, a una ejecución de ese proyecto.
reporters: ['default', ['@probara/vitest-reporter', { projectId: 'SHOP', projects: ['WEB'] }]],import { probara } from '@probara/vitest-reporter';import { test } from 'vitest';
test('SHOP-12 pays', () => {});
test('WEB-3 shows the landing page', () => {});
test('API-7 answers the health check', () => {});
test('opens the help', () => { probara.id('API-9');});$ npx vitest run[probara] Did not send the results linked to cases of API: API is neither the project (SHOP) nor one of projects (PROBARA_PROJECTS) (first seen in "opens the help"; repeats are logged at debug)[probara] Sending 3 results of 3 tests (3 passed, 0 failed, 0 skipped, 0 blocked); 1 linked only to cases of unlisted projects[probara] Recorded 2 results (1 new case, 0 unmatched) in R-1 of SHOP (closed): https://app.probara.net/projects/SHOP/runs/R-1[probara] Recorded 1 result (0 new cases, 0 unmatched) in R-2 of WEB (closed): https://app.probara.net/projects/WEB/runs/R-2PROBARA_PROJECTS=WEB,API los lista desde el entorno.
Qué va a dónde
Sección titulada «Qué va a dónde»- Según el proyecto del caso. Un resultado vinculado a
WEB-3va a una ejecución deWEB. Los IDs de cada proyecto listado también vinculan desde los títulos, y salen de la clave, igual que los del proyecto configurado. - Una prueba vinculada a casos de varios proyectos se envía una vez por caso, cada una a su proyecto, con sus archivos subidos a cada resultado.
- Una prueba sin caso va al proyecto configurado (
projectId), donde se asocia por su clave o se crea: las claves de automatización pertenecen a un proyecto, así que solo el proyecto configurado crea casos, bajosuiteUlid. - Un ID de un proyecto que no está listado en un título (
API-7, arriba) no es un ID: queda en el título y en la clave, como cualquier texto, y la prueba va al proyecto configurado. Pasado aprobara.id()(API-9), es un caso que el reporter no puede enviar a ningún sitio: el resultado acabaría en el proyecto equivocado, donde Probara rechaza su ID. Se deja fuera, con una advertencia por proyecto, y el recuento de la líneaSendinglo indica. Lista el proyecto para reportarlo.
Una ejecución por proyecto
Sección titulada «Una ejecución por proyecto»Cada proyecto listado tiene su propia ejecución, creada con su primer resultado (un proyecto sin resultados no tiene ejecución), con el mismo nombre, descripción, entorno (por nombre), etiquetas y origen de CI que la del proyecto configurado, y cerrada al final como cualquier ejecución que crea el reporter.
El hito, el plan y las configuraciones son entidades de planificación de un proyecto: un nombre que
existe en SHOP puede no existir en WEB, donde Probara rechazaría todo el informe. Por eso
run.milestone, run.plan y run.configurations, igual que sus formas con ULID
(run.milestoneId, run.configurationUlids, run.environmentId), solo van con la ejecución del
proyecto configurado, y una advertencia los nombra. Para dar los suyos a la ejecución de otro
proyecto, créala primero y reutilízala:
WEB_RUN=$(npx @probara/cli run create --project WEB --milestone "Web sprint 4")PROBARA_RUN_ULIDS="WEB=$WEB_RUN" PROBARA_PROJECTS=WEB npx vitest runrun.ulids (PROBARA_RUN_ULIDS=SHOP=<ulid>,WEB=<ulid>) nombra la ejecución que se reutiliza en
cada proyecto; la entrada del proyecto configurado cuenta como run.ulid. Una ejecución reutilizada
queda abierta salvo que closeRun sea true: ciérrala con
probara run close --project WEB --run-ulid <ulid>.
Jobs con sharding y varios proyectos
Sección titulada «Jobs con sharding y varios proyectos»Los shards que envían cada uno sus propios resultados (sin el reporter blob) comparten ejecuciones
del mismo modo: crea una ejecución por proyecto antes de los shards, pásalas todas en
PROBARA_RUN_ULIDS, y ciérralas después del último shard
(patrón 2):
SHOP_RUN=$(npx @probara/cli run create)WEB_RUN=$(npx @probara/cli run create --project WEB)export PROBARA_PROJECTS=WEB PROBARA_RUN_ULIDS="SHOP=$SHOP_RUN,WEB=$WEB_RUN"npx vitest run --shard=1/2npx vitest run --shard=2/2npx @probara/cli run close --run-ulid "$SHOP_RUN"npx @probara/cli run close --project WEB --run-ulid "$WEB_RUN"Cuando se reutiliza la ejecución del proyecto configurado pero un proyecto listado no tiene
ejecución en run.ulids, cada shard crea su propia ejecución en ese proyecto, y una advertencia lo
indica. Los shards que escriben un blob no envían nada: vitest --merge-reports reporta una sola
vez los resultados de todos los proyectos, como una sola ejecución.
Un informe fallido solo detiene su proyecto: los demás continúan. El registro nombra el proyecto de
cada error (WEB: ...), y un
archivo de resultados
guarda lo que cada proyecto no pudo enviar, con la ejecución a la que vuelve: un solo archivo para
toda la ejecución, que probara import results 'probara-results*.json' envía a cada proyecto.
Relacionado: Proveedores de CI · Resultados y reintentos · CLI · Fuente: ci/sharding.md, projects.md