El problema de la confianza
Un test inestable (flaky) es aquel que pasa y falla de forma intermitente sin que haya ningún cambio en el código. Parece algo menor, hasta que te das cuenta de lo que le hace a tu equipo. Cuando los tests fallan de manera errática, los desarrolladores dejan de confiar en la suite. Repiten las ejecuciones fallidas «solo para comprobar». Hacen merge a pesar de builds en rojo. Con el tiempo, todo el pipeline de CI se convierte en ruido de fondo que nadie vigila.
El coste real no son los tests inestables en sí, sino la erosión de la cultura de testing que tanto esfuerzo te costó construir.
Por qué los tests fallan de forma errática (los sospechosos habituales)
- Dependencias de tiempo: Tests que dependen de setTimeout, de la finalización de animaciones o de la velocidad de red sin esperas adecuadas. Es la causa número 1 en las suites E2E.
- Estado compartido: Tests que dependen del estado de la base de datos, del almacenamiento del navegador o de variables globales dejadas por una prueba anterior en la misma ejecución.
- Variabilidad del entorno: Tests que pasan en local pero fallan en CI por diferencias en resolución de pantalla, zona horaria, idioma o restricciones de recursos.
- Datos no deterministas: Tests que se basan en IDs aleatorios, marcas de tiempo o respuestas de APIs de terceros que cambian entre ejecuciones.
- Condiciones de carrera: Tests que hacen clic antes de que un componente sea interactivo, o que realizan aserciones antes de que una operación asíncrona haya concluido.
Nuestro framework de 4 pasos para eliminar la inestabilidad
Paso 1: Aislar de inmediato
En el momento en que se identifica un test inestable, muévelo a una suite de cuarentena. Sigue ejecutándose, pero no bloquea el build. Esto preserva la confianza en CI mientras investigas.
Paso 2: Reproducir y clasificar
Ejecuta el test inestable entre 50 y 100 veces de forma aislada. Si falla de manera consistente a una tasa determinada (por ejemplo, el 15 % de las ejecuciones), tienes un patrón reproducible. Clasifica la causa raíz: tiempo, estado, entorno o datos.
Paso 3: Corregir la causa raíz, no el síntoma
Añadir lógica de reintento o aumentar los timeouts es un parche, no una solución. Para problemas de tiempo, usa patrones correctos de espera por condición. Para estado compartido, garantiza el aislamiento entre tests. Para variabilidad de entorno, conteneriza tu runner de CI.
Paso 4: Monitorizar la recurrencia
Tras la corrección, realiza un seguimiento de la tasa de éxito del test durante 2 semanas antes de reintegrarlo en la suite principal. Si vuelve a ser inestable, el análisis de causa raíz fue incompleto.
Una suite saludable tiene una tasa de inestabilidad inferior al 0,5 %. Por encima del 2 %, tienes un problema sistémico que requiere inversión dedicada. Por encima del 5 %, tu pipeline de CI es, en la práctica, decorativo.
Mejor prevenir que curar
La mejor estrategia contra la inestabilidad es escribir tests estables desde el principio. Nuestros frameworks imponen patrones que previenen las causas más comunes: selectores con auto-espera, contextos de test aislados, factorías de datos deterministas y entornos de ejecución contenerizados. La prevención cuesta menos que todos los ciclos de triaje que jamás tendrás que afrontar.