Ir al contenido

Ejecuciones de Playwright con shards

Fuera de GitHub Actions, cada playwright test crea su propia ejecución por defecto, así que cuatro shards son cuatro ejecuciones. En GitHub Actions los shards de un mismo workflow comparten una ejecución automáticamente (jobs en paralelo). En otros entornos, para tener una ejecución para todo el pipeline, elige uno de estos dos patrones. Cada job que envía resultados necesita PROBARA_API_TOKEN, configurado como en la sección de tu proveedor de CI.

PatrónElígelo cuando
1. Combinar los informes blobEs lo más simple, y la forma propia de Playwright. Un solo job envía; si un shard falla, no queda ninguna ejecución abierta.
2. Crear la ejecución, enviar desde cada shard, cerrarlaLos resultados deben aparecer mientras se ejecutan los shards.

Los workers en paralelo de un mismo playwright test no necesitan nada: todos envían a través del único reporter del proceso principal, a una sola ejecución.

Cada shard escribe un informe blob de Playwright y lo guarda como artefacto; un último job los combina con el reporter. La ejecución combinada contiene cada intento de cada shard, con las mismas claves que una ejecución de toda la suite, y los archivos que llevan los informes blob (capturas, trazas, archivos de testInfo.attach()).

  1. Registra blob en CI y el reporter en el resto de entornos:

    playwright.config.ts
    import { defineConfig } from '@playwright/test';
    export default defineConfig({
    reporter: process.env.CI ? 'blob' : [['list'], ['@probara/playwright-reporter']],
    });
  2. Ejecuta cada shard: npx playwright test --shard=1/4 escribe blob-report/. Los shards no necesitan token.

  3. Reúne cada blob-report/ en una carpeta y combínala con el token en el entorno:

    Ventana de terminal
    npx playwright merge-reports --reporter @probara/playwright-reporter ./all-blob-reports

Para pasar opciones al reporter al combinar, ponlas en una configuración para la combinación (npx playwright merge-reports --config merge.config.ts ./all-blob-reports):

merge.config.ts
export default {
testDir: './tests',
reporter: [['@probara/playwright-reporter', { projectId: 'SHOP', run: { tags: ['sharded'] } }]],
};

Mantén testDir igual que en playwright.config: las claves son relativas a él. Los workflows completos están en las secciones de GitHub Actions, GitLab CI y Bitbucket Pipelines.

Crea la ejecución, envía desde cada shard y ciérrala:

  1. Un primer job ejecuta probara run create, que crea una ejecución automatizada vacía e imprime su ULID en stdout.
  2. Cada shard se ejecuta con ese ULID en PROBARA_RUN_ULID. Un shard nunca cierra una ejecución que no creó, así que todos envían a la ejecución abierta. Probara concilia los shards que envían en el mismo momento: ningún caso se añade dos veces a la ejecución.
  3. Un último job ejecuta probara run close, después de todos los shards, incluso cuando alguno falló.

En un shell, el flujo completo es:

Ventana de terminal
PROBARA_RUN_ULID=$(npx @probara/cli run create)
export PROBARA_RUN_ULID
npx playwright test --shard=1/2
npx playwright test --shard=2/2
npx @probara/cli run close

Asigna el ULID en su propia línea: export PROBARA_RUN_ULID=$(...) ocultaría una creación fallida. En CI, los jobs de abajo fijan la versión de la CLI (npx --yes @probara/cli@0.2), que no es una dependencia del reporter; con @probara/cli en tus devDependencies, npx @probara/cli después de npm ci ejecuta la versión del lockfile. probara es la CLI de Probara; usa el mismo token y el mismo proyecto. Las opciones de una ejecución nueva van a run create (--run-name, --environment, --milestone, --plan, --tag…), porque los shards reutilizan la ejecución e ignoran sus propias opciones de ejecución.

jobs:
probara-run:
runs-on: ubuntu-latest
outputs:
ulid: ${{ steps.create.outputs.ulid }}
env:
PROBARA_API_TOKEN: ${{ secrets.PROBARA_API_TOKEN }}
PROBARA_PROJECT: SHOP
# A fork's build gets no secret: reporting off, so run create prints nothing and exits 0.
PROBARA_ENABLED: ${{ secrets.PROBARA_API_TOKEN != '' }}
steps:
- uses: actions/setup-node@v5
with:
node-version: 22
- id: create
run: |
ulid=$(npx --yes @probara/cli@0.2 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 playwright install --with-deps
- run: npx playwright test --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }}
env:
PROBARA_API_TOKEN: ${{ secrets.PROBARA_API_TOKEN }}
PROBARA_PROJECT: SHOP
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 --yes @probara/cli@0.2 run close
env:
PROBARA_API_TOKEN: ${{ secrets.PROBARA_API_TOKEN }}
PROBARA_PROJECT: SHOP
PROBARA_RUN_ULID: ${{ needs.probara-run.outputs.ulid }}

Sin token, la CLI termina con código 2, así que el primer job define PROBARA_ENABLED según esté o no el secreto: en el build de un fork, run create no imprime nada y termina con código 0, los shards no envían nada y el job de cierre se omite.

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 --yes @probara/cli@0.2 run create)
- echo "PROBARA_RUN_ULID=$PROBARA_RUN_ULID" > probara.env
artifacts:
reports:
dotenv: probara.env
playwright:
stage: test
image: mcr.microsoft.com/playwright:v1.56.1-noble
parallel: 4
variables:
PROBARA_PROJECT: SHOP
script:
- npm ci
- npx playwright test --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 --yes @probara/cli@0.2 run close

.pre y .post son la primera y la última etapa integradas en GitLab; when: always cierra la ejecución incluso después de shards fallidos. CircleCI, Azure Pipelines y Buildkite usan el mismo patrón: consulta sus secciones de proveedores de CI.

Una ejecución sigue abierta hasta que se cierra. Ciérrala a mano, con el ULID del registro del job de creación:

Ventana de terminal
npx @probara/cli run close --run-ulid 01J9Z3K4M5N6P7Q8R9S0T1V2W3
Algo sale malPatrón 1 (combinar)Patrón 2 (ejecución compartida)
Un shard falla antes de terminarFalta su informe blob; el resto se envíaSus resultados hasta ese momento están en la ejecución
Probara no está accesibleEl job de combinación no consigue enviar; vuelve a lanzarloEl archivo de resultados de cada shard lo conserva (un archivo hermano en un disco compartido)
El job de cierre no se ejecutaNo hay nada que cerrarLa ejecución queda abierta: ciérrala a mano

Una suite de Playwright puede contener las pruebas de varios proyectos de Probara: una suite end-to-end compartida cuyos casos están en SHOP, WEB y API. Lista los otros proyectos en projects (PROBARA_PROJECTS=WEB,API), y cada resultado va al proyecto de su caso, a una ejecución de ese proyecto.

reporter: [['@probara/playwright-reporter', { projectId: 'SHOP', projects: ['WEB'] }]],
tests/shared.spec.ts
import { test } from '@playwright/test';
test('SHOP-12 pays', async () => {});
test('WEB-3 shows the landing page', async () => {});
test(
'answers the health check',
{ annotation: { type: 'probara_case', description: 'API-7' } },
async () => {},
);
test('opens the help', async () => {});
$ npx playwright test
[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 "answers the health check"; 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-2
  • Según el proyecto del caso. Un resultado vinculado a WEB-3 va a una ejecución de WEB. Los IDs de cada proyecto listado también se 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 busca por su clave o se crea: las claves de automatización pertenecen a un proyecto, así que solo el proyecto configurado crea casos, bajo suiteUlid.
  • Un caso de un proyecto que no está listado no se envía: acabaría en el proyecto equivocado, donde Probara rechaza su ID. Una advertencia por proyecto lo indica, y el recuento del registro deja fuera esos intentos. Lista el proyecto para enviarlo.

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 antes y reutilízala:

Ventana de terminal
WEB_RUN=$(npx @probara/cli run create --project WEB --milestone "Web sprint 4")
PROBARA_RUN_ULIDS="WEB=$WEB_RUN" PROBARA_PROJECTS=WEB npx playwright test

run.ulids (PROBARA_RUN_ULIDS=SHOP=<ulid>,WEB=<ulid>) nombra la ejecución que reutilizar 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>.

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:

Ventana de terminal
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 playwright test --shard=1/2
npx @probara/cli run close --run-ulid "$SHOP_RUN"
npx @probara/cli run close --project WEB --run-ulid "$WEB_RUN"

Si 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.

Un informe fallido solo detiene su proyecto: los demás siguen. El registro nombra el proyecto de cada error (WEB: ...), y un archivo de resultados conserva 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.

Siguiente: proveedores de CI, o la referencia de probara run create y run close (en inglés).