Resultados, estados y reintentos en Cypress
Cada cypress run reporta en una ejecución de Probara: una ejecución automatizada nueva por defecto,
cerrada al final, o una existente. Cada intento de cada prueba es un resultado en ella, con el
veredicto del propio Cypress. Esta página cubre la ejecución, los estados, los reintentos, qué pasa
cuando los resultados no se pueden enviar y quién recibe los fallos.
La ejecución
Sección titulada «La ejecución»El plugin crea la ejecución, envía a ella cada resultado de cada spec y la cierra cuando Cypress termina la ejecución. Estas opciones describen la ejecución que crea:
reporterOptions: { projectId: 'SHOP', run: { name: 'Nightly regression', description: 'Every night on main, against staging.', environment: 'staging', milestone: 'Sprint 12', plan: 'PLAN-2', configurations: [ { group: 'Browser', name: 'Chrome' }, { group: 'OS', name: 'Linux' }, ], tags: ['nightly', 'e2e'], },},| Opción | Variable | Qué define |
|---|---|---|
run.name | PROBARA_RUN_NAME | El nombre. Por defecto: el nombre del build de CI (CI #42), si no Automated run <date> <time> UTC |
run.description | PROBARA_RUN_DESCRIPTION | Para qué es la ejecución |
run.environment | PROBARA_ENVIRONMENT | El entorno, por nombre: se crea en el proyecto si ninguno tiene ese nombre |
run.milestone | PROBARA_MILESTONE | El hito, por ID visible (M-3) o nombre exacto |
run.plan | PROBARA_PLAN | El plan de pruebas, por ID visible (PLAN-2) o nombre: la ejecución empieza con los casos del plan |
run.configurations | PROBARA_CONFIGURATIONS | Valores de configuración por grupo y nombre (Browser=Chrome,OS=Linux), cada grupo una vez |
run.tags | PROBARA_RUN_TAGS | Etiquetas (nightly,e2e) |
La misma ejecución desde el entorno de un paso de CI, con el proyecto en la configuración:
PROBARA_RUN_NAME="Nightly regression" PROBARA_ENVIRONMENT=staging PROBARA_RUN_TAGS=nightly,e2e npx cypress runUn nombre de más de 200 caracteres se recorta, y también una etiqueta de más de 80; las etiquetas que pasan de 50 se descartan, con una advertencia. Un entorno, un hito o un plan que supera su límite desactiva el envío, nombrando el campo: tiene que coincidir con un nombre de Probara, y uno recortado no coincidiría con ninguno.
Sin el plugin, cada spec reporta en una ejecución propia, porque Cypress nunca avisa al reporter de cuándo terminó toda la ejecución (registro).
Nombres o ULIDs
Sección titulada «Nombres o ULIDs»El entorno, el hito y las configuraciones aceptan también 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 las dos: las dos a la vez es
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 informe (
422, nombrando el campo): no se registra nada, y el registro dice por qué. Comprueba los nombres en Probara.
Origen de la ejecución
Sección titulada «Origen de la ejecución»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 (qué rellena cada CI). Sustituye un
campo con source o su variable, o no envíes ninguno:
| Opción | Variable | Valor por defecto |
|---|---|---|
source.branch | PROBARA_BRANCH | detectado del CI |
source.commit | PROBARA_COMMIT | detectado del CI |
source.buildUrl | PROBARA_BUILD_URL | detectado del CI |
source: false | — | no envía origen |
Una ejecución existente
Sección titulada «Una ejecución existente»run.ulid (PROBARA_RUN_ULID) reporta en una ejecución que ya existe, como una que
probara run create creó para las máquinas 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 cypress 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[probara] The run R-1 of SHOP stays open: close it in Probara, or with probara run close --project SHOP --run-ulid 01J9Z3K4M5N6P7Q8R9S0T1V2W3Las opciones de una ejecución nueva se ignoran entonces, con una advertencia: la ejecución conserva su propio nombre, entorno, hito y configuraciones.
[probara] Ignored name: a reused run (run.ulid) keeps its ownPara 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ón | Al final de cypress run |
|---|---|
| Creada por el reporter | Se cierra, sea cual sea el código de salida de las pruebas |
Reutilizada (run.ulid, run.ulids) | Queda abierta: la cierra quien la creó |
| Cualquiera, si un informe falló tras sus reintentos | Queda abierta: el registro la nombra, y el error dice qué hacer |
closeRun (PROBARA_CLOSE_RUN) decide para cada ejecución: true cierra también una reutilizada,
false deja abierta una creada. closeRuns decide por proyecto ({ SHOP: true, WEB: false })
cuando closeRun no está definido. Cierra una ejecución a mano con la
CLI de Probara:
npx @probara/cli run close --run-ulid 01J9Z3K4M5N6P7Q8R9S0T1V2W3Estados
Sección titulada «Estados»Cada intento se envía con el veredicto del propio Cypress:
| Lo que reporta Cypress | Estado |
|---|---|
| Una prueba que pasó | passed |
| Una prueba que falló: una aserción, un error, un tiempo agotado | failed |
| Un intento que Cypress va a volver a ejecutar (un reintento) | failed |
it.skip, o this.skip() en la prueba o en un beforeEach | skipped |
Una prueba que un beforeEach fallido impidió ejecutar | skipped |
Un beforeEach o before que falla, reportado como "before each" hook for "…" | failed, con ese nombre |
Una spec que lanza un error al cargarse (An uncaught error was detected outside of a test) | failed |
| Una spec que Cypress no puede analizar | failed, como Spec failed to run |
El reporter nunca envía blocked por su cuenta: mapea un estado a él cuando lo necesites
(mapeo de estados). Un resultado lleva el estado, la duración y la hora
de inicio que reportó Cypress, y el error de un intento fallido en sus notas, con su mensaje y su
traza y sin los colores de la terminal.
Un hook que falla
Sección titulada «Un hook que falla»Un beforeEach o un before no pertenece a ninguna prueba propia: lo que hizo pertenece a la prueba
para la que se ejecuta. Cuando falla, Cypress reporta el fallo con una prueba a la que da el nombre
del hook y de la prueba en curso, y el reporter conserva ese nombre, que es también el que da la
importación JUnit.
Un hook que falla una vez y pasa en el reintento es una prueba con dos resultados: el intento
fallido y el que pasó. Un hook que falla en todos los intentos, con retries.runMode: 1:
describe('Checkout', () => { beforeEach(() => { throw new Error('the cart service is down'); });
it('never runs', () => {}); it('never runs either', () => {});});
describe('Profile', () => { it('still runs', () => {});});cypress/e2e/hooks.cy.js > Checkout never runs failedcypress/e2e/hooks.cy.js > Checkout "before each" hook for "never runs" failedcypress/e2e/hooks.cy.js > Checkout never runs either skippedcypress/e2e/hooks.cy.js > Profile still runs passedCheckout never runses el primer intento de la prueba, que falló porque falló su hook y que Cypress volvió a ejecutar."before each" hook for "never runs"es el fallo que Cypress no pudo superar.Checkout never runs eitherno llegó a ejecutarse: el reporter envía como omitida cada prueba de la suite que no reportó ningún intento, algo que un informe JUnit no puede hacer, porque una prueba así no deja rastro en él. No se sabe que esté rota, solo que no se ejecutó.Profile still runs: unbeforeEachque falla detiene el resto de su propiodescribe, nunca el resto de la spec.
Una spec que Cypress no puede ejecutar
Sección titulada «Una spec que Cypress no puede ejecutar»Una spec cuyo código de nivel superior lanza un error mientras Cypress la carga es un resultado fallido, con el nombre que le da Cypress, y se reintenta como cualquier prueba:
cypress/e2e/throws.cy.js > An uncaught error was detected outside of a testUna spec que Cypress no puede analizar (un error de sintaxis) no ejecuta ninguna prueba. El plugin convierte el fallo que contó Cypress en un resultado fallido, para que una spec rota nunca aparezca en verde:
cypress/e2e/broken.cy.js > Spec failed to runSus notas dicen Cypress could not run this spec: 1 failure(s), no test ran, y su caso queda solo en
la suite de la spec. Sin el plugin, ese resultado no existe.
El código de salida es el de Cypress
Sección titulada «El código de salida es el de Cypress»Cypress termina un cypress run con el número de sus propias pruebas fallidas, y reportar no
cambia nada de eso: una prueba que falla dos veces es una prueba fallida, y el fallo de un hook es
una prueba propia. Lo que registró Probara (cada intento, un estado mapeado, un resultado filtrado,
una ejecución que no se pudo enviar) nunca llega al código de salida.
Mapeo y filtro de estados
Sección titulada «Mapeo y filtro de estados»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.
reporterOptions: { projectId: 'SHOP', statusMapping: { failed: 'blocked' } },$ npx cypress run --spec cypress/e2e/cart.cy.js[probara] Sending 5 results of 5 tests (3 passed, 0 failed, 1 skipped, 1 blocked)Con statusFilter: ['failed'] en su lugar, el intento fallido no se envía, y la línea Sending dice
cuántos se dejaron fuera:
[probara] Sending 4 results of 4 tests (3 passed, 0 failed, 1 skipped, 0 blocked); 1 left out by statusFilterComo 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. Cypress sigue haciendo fallar el
comando: el mapeo y el filtro solo cambian lo que registra Probara.
- Filtrar
skippeddeja fuera mucho: cadait.skipy cada prueba que un hook fallido impidió ejecutar. blockeddistingue los fallos que no son de la propia prueba: mapeafailedablockedcuando el fallo de un hook no deba leerse como una prueba que falla.
Reintentos y pruebas inestables
Sección titulada «Reintentos y pruebas inestables»Cada intento es un resultado propio, en el orden en que se ejecutaron los intentos, cada uno con su
estado, su duración, su error, sus pasos y sus archivos. Cuántos intentos hace Cypress lo decide su
propio ajuste, retries:
module.exports = defineConfig({ e2e: { reporter: '@probara/cypress-reporter', reporterOptions: { projectId: 'SHOP' }, setupNodeEvents(on, config) { return probaraNodeEvents(on, config); }, retries: { runMode: 1 }, },});$ npx cypress run --spec cypress/e2e/retry.cy.js[probara] Sending 2 results of 1 test (1 passed, 1 failed, 0 skipped, 0 blocked)- Qué muestra Probara. El caso de la ejecución conserva el último resultado (
passedaquí), y cada intento queda en su historial: una prueba inestable es un caso cuyo historial mezcla fallos y aciertos en la misma ejecución. La líneaSendinglo muestra: más resultados que pruebas. - El número de intento. Desde el segundo intento, el resultado lleva un parámetro
attempt(2,3, …), junto abrowser. Ninguno forma parte de la clave de automatización. - Sin marca de inestable. Los propios intentos son la evidencia.
probara import junitsolo conserva el último intento de una prueba reintentada, así que una batería que pasa de la importación JUnit al reporter gana los intentos anteriores en el historial de cada caso inestable. - Cada intento empieza vacío. Lo que dijeron los helpers
probara.*pertenece al intento que lo dijo: los pasos, los archivos y los metadatos de un reintento son suyos, nunca heredados. - Capturas de un reintento. Cada intento fallido recibe la captura que Cypress tomó para él.
- El resumen propio de Cypress cuenta cada prueba una vez, por su último intento; Probara cuenta cada intento.
Para enviar solo el último intento, no reintentes en Cypress: ninguna opción del reporter descarta intentos.
Archivo de resultados
Sección titulada «Archivo de resultados»Cuando un informe no se puede enviar (Probara inalcanzable, un token rechazado, un informe que falló
tras sus reintentos), sus resultados se pierden salvo que los guardes. Define un archivo de
resultados, y el reporter escribe en él lo que no pudo enviar; probara import results lo envía más
tarde, a las mismas ejecuciones.
reporterOptions: { projectId: 'SHOP', resultsFile: 'results/probara-results.json' },O PROBARA_RESULTS_FILE=results/probara-results.json, relativo al directorio desde el que se lanzó
cypress run.
$ npx cypress run[probara] Sending 1 result of 1 test (1 passed, 0 failed, 0 skipped, 0 blocked)[probara] 1 result was not sent: Probara answered 403 forbidden: <message from Probara>. No run was created or updated[probara] Wrote the 1 result that was not sent to /work/shop/results/probara-results.json: send them with probara import results /work/shop/results/probara-results.jsonDespués, desde cualquier job que tenga el token, envía lo que quedó pendiente:
npx @probara/cli import results 'results/probara-results*.json'Pon el glob entre comillas: probara lo expande, y coincide con el archivo y sus hermanos.
- Solo cuando hace falta. El archivo solo se escribe cuando algo no se envió: cuando todos los resultados llegaron, no hay archivo.
- A las mismas ejecuciones. El archivo nombra las ejecuciones a las que pertenecen sus
resultados, los ajustes que los enviaron (proyecto, ejecución,
rootDir,createMissingCases) y cada resultado tal como lo construyó el reporter, así que llega a los mismos casos desde cualquier máquina. Nunca el token. - Nunca encima de un archivo anterior. Cuando ya hay un archivo en esa ruta (el de otra máquina,
o el de una ejecución anterior), el reporter escribe en el primer hermano libre:
probara-results-2.json, después-3, y así sucesivamente. - Estados antes del mapeo. El archivo guarda cada estado antes de
statusMapping, que se vuelve a aplicar al enviar el archivo.
Qué viaja con el archivo
Sección titulada «Qué viaja con el archivo»| Archivos | En el archivo de resultados |
|---|---|
Cuerpos y archivos de probara.attach(), la salida de consola | Copiados junto a él, en probara-results-attachments/, y nombrados relativos al archivo |
| Capturas y vídeos | Nombrados por su ruta absoluta, sin copiar |
Mueve o descarga el archivo y su carpeta de adjuntos juntos, e impórtalo desde ahí: un artefacto de CI que descarga otro job conserva esos adjuntos. Una máquina que nunca tuvo las capturas y los vídeos no puede enviarlos.
Envío desactivado: guardarlo todo
Sección titulada «Envío desactivado: guardarlo todo»Con el envío desactivado (PROBARA_ENABLED=false, o sin token), el reporter escribe todos los
resultados en el archivo. Ejecuta las pruebas donde no hay token, y envía el archivo desde un job que
lo tenga:
PROBARA_ENABLED=false PROBARA_PROJECT=SHOP PROBARA_RESULTS_FILE=results/probara-results.json npx cypress runnpx @probara/cli import results 'results/probara-results*.json'El mismo archivo muestra qué se enviaría sin enviarlo
(comprobar qué se enviaría).
La importación (varios archivos y globs, --dry-run, códigos de salida) está en
probara import results
(en inglés).
Asignar resultados fallidos
Sección titulada «Asignar resultados fallidos»assignFailedTo nombra a las personas que revisan los fallos. Cada informe pide a Probara que asigne
cada caso de la ejecución que deja fallido, y que aún no tiene responsable, a una de ellas, por
turnos, para que una ejecución nocturna fallida llegue a la lista de alguien sin que nadie tenga que
clasificarla antes.
reporterOptions: { projectId: 'SHOP', assignFailedTo: ['ana@example.com', 'bo@example.com'],},O desde el entorno: PROBARA_ASSIGN_FAILED_TO=ana@example.com,bo@example.com.
| Regla | Por qué |
|---|---|
Solo los casos de la ejecución que un informe deja en failed | Los resultados que pasaron, omitidos o bloqueados no necesitan a nadie |
| Solo los casos de la ejecución sin responsable | Nunca se sustituye a un responsable: alguien ya se ocupa |
| Solo miembros activos que pueden ejecutar pruebas en el proyecto | Un caso no se puede asignar a quien no puede trabajar en él |
| Los miembros indicados se turnan, en el orden en que los indicas | Los fallos se reparten, no se acumulan en el primer nombre |
| Un email que no coincide con ningún miembro así se omite | Los resultados se registran igualmente; la advertencia de Probara los cuenta |
- Decide el último intento. Una prueba inestable que pasa en su reintento deja su caso en
passed, así que nunca se asigna, por muchos intentos suyos que fallaran. - Después de
statusMapping. ConstatusMapping: { failed: 'blocked' }, nada queda fallido, así que nada se asigna. - La advertencia nunca nombra los emails, solo cuántos se omitieron:
[probara] Probara warned: <message from Probara>. - La lista se recorta y se deduplica. Más de 20 emails, o un valor que no es un email, desactiva
el envío, nombrando
assignFailedTo.
Relacionado: Configuración · Sharding y proyectos · Solución de problemas · Fuente: runs.md, statuses.md, specs.md, retries.md, results-file.md, assign-failed.md