Nunca conviertas un test intermitente en una compuerta obligatoria
Volver a correr un build en rojo es entrenar a tu equipo para ignorar CI. La primera vez que un check obligatorio se pone en rojo y alguien le da a "re-run" y se pone verde, aprendió una lección: rojo no significa roto, significa intenta de nuevo. Repítelo unas cuantas decenas de veces y toda la suite se vuelve ruido de fondo — nadie lee la falla, solo reintentan hasta que el dado cae en verde.
Pasar al reintentar es un defecto, no un tropiezo
Un test que pasa en la segunda corrida sin cambiar el código es, por definición, no determinista. Algo tuvo una condición de carrera: una suposición de tiempo, un fixture compartido, un global dependiente del orden, una llamada de red sin mock. La intermitencia es una señal — muchas veces es el único síntoma de una condición de carrera real que también tienes en producción. Cuando la tapas con reintentos automáticos, tiras la señal y te quedas con el bug.
Martin Fowler lo puso sin rodeos: los tests no deterministas son "una infección virulenta que puede arruinar por completo toda tu suite de tests". Su aritmética es lo que asusta — una suite de 100 tests con apenas 10 intermitentes fallará en la mayoría de las corridas. Y "una vez que se pierde esa disciplina, una falla en los tests deterministas sanos también se ignora". Una intermitencia no te cuesta un test. Te cuesta la credibilidad de todos.
Pon en cuarentena, no lo hagas obligatorio
El arreglo es aburrido y funciona: mantén el test intermitente fuera de la compuerta obligatoria. Tres movimientos, en orden:
| Paso | Qué haces | Qué NO debes hacer |
|---|---|---|
| 1. Cuarentena | Mueve el test a una suite no bloqueante que igual corre y reporta | No lo borres ni le pongas skip — perderías la señal |
| 2. Registra el arreglo | Abre un ticket con dueño y fecha límite | No lo dejes sin dueño — la cuarentena se vuelve un cementerio |
| 3. Reporta, no bloquees | Deja que se muestre en rojo en el PR sin hacer fallar el merge | No agregues retries: 3 al job obligatorio |
El test sigue corriendo. Sigue reportando. Solo que ya no puede tomar de rehén el PR de otra persona mientras alguien persigue la condición de carrera. Ahora verde significa verde: cada check obligatorio que pasa realmente pasó, de forma determinista, y nadie está aprendiendo a darle a reintentar por reflejo.
Trucos para usuarios avanzados
- Ponle tope a la cuarentena. La regla de Fowler del equipo de Mingle: permite como máximo 8 tests en cuarentena, y ninguno por más de una semana. Si llegas al tope, paras el trabajo de features para vaciarla. El tope es lo que evita que la cuarentena se vuelva un cajón de sastre permanente.
- Corre los tests en cuarentena al final. Pon la suite intermitente en el pipeline después de que pasen los tests deterministas sanos. Igual obtienes la cobertura, y el orden presiona al equipo a arreglar las intermitencias en lugar de aceptarlas.
- Nunca cablees reintentos en el job obligatorio. El reintento automático en la compuerta bloqueante es el anti-patrón del que trata todo este tip — es "dale a reintentar hasta que salga verde" institucionalizado. Si reintentas, reintenta solo en el carril no bloqueante de cuarentena.
- Mide la tasa de intermitencia. Un test que falla 1 de cada 50 corridas es material de cuarentena mucho antes de que un humano note el patrón. Registra pass/fail por test y pon en cuarentena por umbral, no por intuición.
Recursos
- Eradicating Non-Determinism in Tests — Martin Fowler (el mecanismo de cuarentena, el tope de 8 tests, el argumento de la "infección virulenta")
- Flaky Tests at Google and How We Mitigate Them — Google Testing Blog
- About protected branches — GitHub Docs (qué es un required status check y cómo bloquea los merges)
- Test Quarantine — Mergify
¿Desarrollas con agentes de IA? Yeda AI ayuda a los equipos a construir disciplina de CI y de tests en la que los agentes (y las personas) pueden confiar.