← Volver al blog

Cuando todos los tests bloquean, verificar un cambio chico cuesta una hora

2026-09-23

Cuando todos los tests bloquean, verificar un cambio chico cuesta una hora

Tu pipeline arrancó rápido. Después alguien sumó los end-to-end, porque atajaron un bug real. Después la revisión de seguridad, porque atajó otro. Ninguno de esos chequeos está de más —por eso nadie propone sacarlos— y hoy verificar un cambio de dos archivos tarda más que escribirlo.

Es una pendiente natural: agregás una verificación porque detecta algo real; como detecta algo real, no querés que se saltee; entonces la hacés obligatoria. Repetí eso cinco veces en tres meses y terminé con cerca de una hora de controles colgando de cada tarea, por chica que fuera.

Lo que lo destrabó no fue borrar chequeos ni hacerlos más rápidos. Fue cambiar la pregunta: no ¿este chequeo sirve? —todos servían— sino ¿qué decisión bloquea este chequeo?. Algunos tienen que bloquear el cambio individual. A otros les alcanza con bloquear el deploy. Mezclar las dos cosas es exactamente lo que convierte un pipeline en un embudo.

Abajo está cómo quedó partido y, sobre todo, cómo hice el cambio sin romper producción: el control de calidad era la pieza de la que dependía todo lo demás.

La parte cara era la revisión de interfaz

Dentro del control, la verificación más lenta era la revisión de interfaz asistida por modelo: un agente que abre el navegador, recorre la aplicación y evalúa si lo implementado se ve y se comporta como corresponde.

Es valiosa. Encuentra cosas que ningún test automatizado detecta. Y es carísima en tiempo, porque implica levantar el entorno, navegar, esperar cada pantalla y razonar sobre lo que ve.

Correr eso en cada tarea era el equivalente a pedirle a un diseñador que revise la aplicación completa cada vez que alguien cambia una línea de código.

La pregunta correcta no es si el chequeo sirve

El cambio de pregunta reordenó todo, y la razón es económica antes que conceptual: no es lo mismo un control que impide cerrar una tarea que uno que impide desplegar a producción. Tienen costos de espera completamente distintos. El primero se paga decenas de veces por semana; el segundo, una vez por release. Mezclarlos es lo que hace que un equipo termine desactivando los dos.

De ahí salieron los dos niveles.

Nivel 1: lo que bloquea cada tarea

Rápido, determinista y por tarea. Tres cosas: la suite completa del backend, los tests end-to-end propios de esa tarea corriendo sin interfaz gráfica, y una traza de seguridad.

Lo importante es el "propios de esa tarea". No la suite end-to-end completa: solo las pruebas que corresponden a lo que se acaba de tocar. Eso es lo que baja el tiempo de una hora a minutos.

Nivel 2: lo que bloquea el deploy

Lento, costoso y en lote. Ahí se fueron la suite end-to-end completa y la revisión de interfaz con modelo, que se ejecuta sobre las tareas que el nivel 1 no llegó a cubrir.

Ese lote corre en dos momentos: antes de desplegar, de forma bloqueante, y además todas las noches como red de seguridad. Si algo falla, no traba el trabajo del día — traba la salida a producción, que es donde ese control realmente importa.

En la pantalla la división se hizo visible con dos columnas separadas, una por nivel, cada una con su propio estado. Que se vea importa: si un control no bloquea, tiene que quedar clarísimo que su resultado sigue existiendo y que alguien lo va a mirar.

La parte delicada: cambiar algo de lo que depende todo

Esta es la parte que más me costó y de la que menos se escribe.

El control de calidad es una pieza de la que cuelga todo el sistema. Los pasos de cierre se niegan a marcar una tarea como terminada si el control no aprobó. Y esa aprobación, tal como estaba escrita, exigía explícitamente el resultado de la revisión de interfaz.

O sea: si yo hacía lo intuitivo —sacar la revisión de interfaz del control por tarea— el sistema entero dejaba de poder cerrar tareas. No una parte: todas. Cada cierre habría empezado a fallar buscando un dato que ya nadie producía.

Por eso el plan tiene una regla escrita en mayúsculas: si dejás de producir la señal antes de dejar de exigirla, se rompen todos los cierres.

El orden de implementación quedó fijado en cinco etapas, y la primera es la contraintuitiva:

Es la clase de secuencia que parece burocrática cuando la escribís y te salva el día que la ejecutás. Si hubiera empezado por el paso obvio —sacar la revisión de interfaz— habría roto el cierre de tareas en todos los proyectos gestionados al mismo tiempo.

Un detalle que evitó bastante dolor

Cada chequeo nuevo lee la configuración del proyecto y se auto-omite cuando el proyecto no declara lo que necesita.

Hay proyectos gestionados que no tienen tests end-to-end. Si el control los exigiera, esos proyectos quedarían trabados para siempre por un requisito que no aplica. La regla que quedó es: el control no puede exigir lo que el proyecto no declara tener.

Suena obvio escrito así, pero es el tipo de cosa que descubrís cuando el mismo mecanismo corre sobre proyectos con formas distintas.

El resultado y lo que siguió

El objetivo declarado en el plan era bajar el control por tarea de aproximadamente una hora a minutos, en todos los proyectos a la vez. Eso se consiguió.

Y con el sistema corriendo por fin rápido, quedó expuesto un problema que la lentitud había estado tapando: cada vez que reiniciaba el servidor, perdía el plan de trabajo completo. De eso trata la próxima entrega.