¿Cómo distingo un bug real de una prueba inestable?
Ejecuta la prueba varias veces con los reintentos desactivados y cuenta. Un bug real falla de la misma manera en cada ejecución, y una prueba inestable pasa algunas ejecuciones y falla otras sin que nada haya cambiado. El ejemplo a continuación hace exactamente eso en cualquier máquina con Playwright, y luego muestra lo que Nexus Studio hace con cada resultado.
Por el equipo de Nexus Studio, Verdict System LLC. 27 de octubre de 2026.
¿Cómo puedo distinguirlos en un minuto?
Ejecuta la prueba varias veces seguidas con los reintentos desactivados. Playwright lo hace con dos flags: --retries=0, para que un reintento no pueda ocultar un fallo, y --repeat-each=6, que ejecuta cada prueba seis veces. Luego cuenta los resultados de cada prueba.
- Falló todas las veces: trátalo como un bug hasta que puedas demostrar lo contrario. Un fallo en cada ejecución puede seguir proviniendo del entorno, como una solicitud bloqueada o un host inalcanzable, así que lee el error primero.
- Pasó algunas ejecuciones y falló otras: es inestable. El código y la prueba no cambiaron entre esas ejecuciones, por lo que hay algo inestable involucrado, en la aplicación o en la prueba.
- Pasó todas las veces: nada que ver por ahora. Un defecto que aparece una vez en cincuenta ejecuciones necesita más ejecuciones, o revisar el History de la prueba.
¿Puedo probarlo con un ejemplo ejecutable?
Guarda esto como bug-or-flaky.spec.js. La primera prueba simula un flake: falla una de cada tres ejecuciones. La segunda prueba es un bug real: la página dice "Welcome" y la prueba espera "Welcome back", por lo que ninguna ejecución puede pasar.
import { test, expect } from '@playwright/test';
// Fails on its first attempt of every third run, passes otherwise: a simulated flake.
test('flaky: a slow load now and then', async ({ page }, info) => {
await page.setContent('<h1>Welcome</h1>');
expect((info.repeatEachIndex + info.retry) % 3, 'simulated slow load').not.toBe(0);
});
// Fails the same way every time: the heading says "Welcome", the test expects "Welcome back".
test('real bug: wrong heading', async ({ page }) => {
await page.setContent('<h1>Welcome</h1>');
await expect(page.locator('h1')).toHaveText('Welcome back', { timeout: 300 });
});
Ejecútala seis veces con los reintentos desactivados:
npx playwright test --retries=0 --repeat-each=6
Playwright termina con 8 fallos y 4 pases. El conteo por prueba es lo que responde la pregunta, y es lo que imprimió el reporter de lista, línea por línea:
flaky: a slow load now and then 4 passed, 2 failed
real bug: wrong heading 0 passed, 6 failed
Ahora ejecútala una vez con dos reintentos:
npx playwright test --retries=2
Playwright termina con una prueba en cada grupo. La prueba inestable falló en su primer intento y pasó en el reintento #1. El bug real falló los tres intentos.
1 failed
bug-or-flaky.spec.js:10:1 › real bug: wrong heading
1 flaky
bug-or-flaky.spec.js:4:1 › flaky: a slow load now and then
¿Un reintento exitoso significa que la aplicación está bien?
No. Un reintento que pasa te indica que los intentos no estuvieron de acuerdo, nada más. Si la ejecución se vuelve verde y nadie lo revisa, un defecto intermitente en la aplicación, como una condición de carrera, datos compartidos o una dependencia lenta, se vuelve invisible, y esos están entre los defectos más costosos de encontrar. Lee un resultado inestable como un hallazgo, no como un pase que ignorar, y no asumas que el fallo está en la prueba.
¿Qué hace Nexus Studio con cada resultado?
Nexus Studio registra cada intento y le asigna su propio veredicto al resultado, de modo que un reintento nunca convierte un defecto en una ejecución verde simple.
- FLAKY: la prueba falló, luego un reintento la pasó, y nada fue reparado. Sale con código 0, por lo que el build no se rompe, y el reporte y el History muestran la reserva.
- BREACHED: la prueba falló en un solo intento, y ningún patrón de entorno o harness explica el error. Sale con código 1.
- BREACHED_FLAKY: la prueba falló en su último intento tras un reintento anterior, y ningún patrón de entorno lo explica. Sale con código 1. Compara los intentos antes de reportar un bug.
History mantiene una fila por cada ejecución de cada prueba, así que una prueba que pasa a verde, rojo y verde de nuevo aparece como una tendencia en lugar de desaparecer entre las reejecutadas. La guía de pruebas inestables lista los archivos que deja cada veredicto.
¿Cuáles son los límites?
- La inestabilidad del ejemplo se simula con aritmética para que se repita. La inestabilidad real tiene una causa, y encontrarla sigue siendo trabajo de una persona.
- Seis ejecuciones son un filtro rápido, no estadísticas. Un fallo que ocurre una vez en cincuenta ejecuciones puede pasar seis veces sin problemas.
- Un fallo en cada ejecución no siempre es un error en tu aplicación: una red lenta, una página de bloqueo o un navegador caído también hacen fallar las pruebas. La guía de fallos falsos explica cómo distinguirlos.
- Con los reintentos desactivados, un fallo intermitente en Nexus Studio es un BREACHED, porque solo un reintento puede distinguir FLAKY de un fallo simple. La clasificación lee el texto del error, así que abre metadata.json cuando un veredicto te sorprenda.
¿Dónde puedo verlo?
La guía de veredictos explica en qué orden el motor decide los 14 veredictos, y la página Evidence sigue una prueba fallida a través de cada archivo que deja. La prueba de 30 días ejecuta el mismo motor con tus propias pruebas.