Yeda AI Tips · #073

English

Haz que un test inestable falle diez veces a propósito

¿Test inestable (flaky)? Hazlo fallar diez veces a propósito. Un test que falla una vez en CI y pasa al reintentar puede desperdiciar una semana de re-ejecuciones mientras el equipo discute si es real. La solución empieza con un comando: corre el spec sospechoso repetidamente en tu propia máquina hasta que la falla sea aburrida y reproducible — y entonces depúrala como cualquier otro bug.

Por qué los reintentos ocultan bugs reales

Un reintento que convierte rojo en verde no arregla nada — solo lo reclasifica. Playwright incluso los reporta como una categoría aparte: un test que falla y luego pasa al reintentar se marca como flaky, no como aprobado. Cada pase "flaky" es una condición de carrera, un timeout o un bug de orden que igual llegó a producción. Y como iterar sobre fallas de CI es lento (push, cola, esperar 15 minutos, leer logs), los equipos racionalizan en vez de reproducir: "la infra estaba lenta", "córrelo de nuevo". Diez corridas locales en menos de un minuto terminan esa discusión con datos.

El comando

Apunta Playwright al archivo sospechoso y repítelo:

npx playwright test tests/checkout.spec.ts --repeat-each=10

--repeat-each ejecuta cada test que coincida N veces (por defecto 1). Si es inestable, una falla intermitente que aparece 1 de cada 20 veces en CI normalmente se manifiesta en segundos en tu máquina — ahora tienes un ciclo determinista en vez de un debate.

Ajusta aún más el ciclo:

FlagQué haceCuándo agregarlo
--repeat-each=10Ejecuta cada test N veces (por defecto 1)Siempre — este es el tip
-g "adds to cart"Solo corre tests que coinciden con una regexAcotar a un solo test, no al archivo
--workers=1Un solo worker, sin paralelismoDescartar o confirmar interferencia paralela
--retries=0Cero reintentos (el valor por defecto)Asegurar que nada enmascare la falla
--trace=retain-on-failureConserva el trace completo de las corridas fallidasObtener la línea de tiempo de la falla
--headedCorre con navegadores visiblesVer la condición de carrera en vivo

Compara dos corridas: --repeat-each=10 --workers=1 contra --repeat-each=10 con los workers por defecto. ¿Falla solo con paralelismo? Hay estado compartido entre tests. ¿Falla de las dos formas? El bug está dentro del test o de la app — casi siempre una espera faltante o una carrera real.

Arregla la carrera, no el síntoma

Cuando ya falla a demanda, el modo de falla suele ser uno de tres: el test hace la aserción antes de que la app se estabilice (arregla la condición de espera, no agregues un sleep), dos tests comparten estado (aísla el fixture), o la app tiene una carrera real (felicidades — el test inestable hizo su trabajo). --trace=retain-on-failure te da el trace paso a paso de exactamente las corridas que fallaron.

La cuarentena es el último recurso, no el primero. Si debes estacionar un test, test.fixme() de Playwright lo marca como fallido y omite su ejecución — visible en los reportes, a diferencia de un test borrado — y test.fail() lo ejecuta verificando que efectivamente falle, así te enteras en cuanto el bug desaparezca. Abre el issue al poner el test en cuarentena; un fixme sin dueño es un borrado con pasos extra.

Nivel experto: la misma jugada en cualquier stack

Recursos

¿Construyendo una funcionalidad con IA? Yeda AI diseña, audita y lleva a producción sistemas LLM.

Habla con nosotros · Lee el blog · Read in English