Con el arranque de Q3, la presión por entregar el sistema de torneos sube de golpe. Anton empuja una implementación rápida y sucia de la UI de matchmaking y dice que TDD solo estorba. Mariana insiste en la disciplina. Cuando un bug crítico explota en el nuevo entorno de staging, el equipo entiende el costo real de ir rápido sin pruebas.

Los dedos de Anton martillaban el teclado mecánico, y el clac-clac-clac de los switches azules sonaba como una ametralladora pequeña en el silencio del lunes por la mañana.
—No necesito una prueba para esto, Mariana —dijo Anton sin levantar la vista—. Es un controlador de UI: clic, transición de la máquina de estados a “Searching” y disparo de la API de matchmaking. Treinta líneas. Cinco minutos.
—¿Y cómo sabes que la máquina de estados transiciona bien si la API va lenta? —preguntó Mariana con voz plana—. ¿O si la persona usuaria toca dos veces?
—Porque desactivo el botón al hacer clic —dijo Anton, ajustándose las gafas—. matchmakingButton.interactable = false; en la línea doce. Doble toque imposible.
—¿Y si falla la llamada y el botón queda desactivado para siempre? —preguntó Stefan, tomando un sorbo de café—. La persona queda atrapada en un estado muerto de UI y solo puede forzar cierre.
Anton resopló. —Ustedes dos son un dúo del apocalipsis. Es lunes. Lukas quiere un prototipo funcionando de lobby de torneos para el sync del miércoles. Si hoy me pongo a escribir unit tests de UI en Unity —que ya son un dolor por el lifecycle— no le muestro nada.
—Lukas quiere ver progreso —dijo Mariana—. Pero “progreso” construido sobre supuestos es un préstamo que pagamos con intereses la semana siguiente. Todo Q2 lo pasamos pagando tus préstamos, Anton.
—Eso era backend —replicó Anton, volviendo al teclado—. UI es distinto. Es visual. Si se ve bien, el 90% del tiempo está bien. Escribo tests luego, te lo prometo. Déjame sacar primero el flujo.
Stefan lo miró volver a teclear. Era la trampa clásica: la ilusión de velocidad. Cuando se escribe sin pruebas, todo parece productivo. Las líneas suben rápido. Las transiciones se ven suaves en local.
Pero la fricción no desaparece. Solo se aplaza. Y estaba esperando en el nuevo staging, donde la red no era local, la base no estaba vacía y la latencia no era cero.
—Seis semanas de cordura —murmuró Mariana a Stefan mientras caminaban hacia la zona de backend—. Y Anton ya quiere gastarlas en atajos.
—Está bajo presión —dijo Stefan—. Y siendo justos, hacer unit tests de controladores UI en Unity es molesto. Pero va a aprender. Hay lecciones que no se enseñan en una pizarra. Se sienten.

—Despliegue en staging completo —dijo Hassan, echándose hacia atrás y frotándose los ojos—. Réplicas multirregión activas en EU-West, US-East y AP-East. Staging ahora refleja el escalado de producción. Anton, despliega tu build de UI.
Anton sonrió. —Atentos, equipo backend. El lobby de torneos sale a staging.
Lanzó el script. En su segundo monitor, Unity compiló y empujó al servidor de staging. En dos minutos, la UI del lobby apareció en su tablet de prueba.
—Lobby abierto —anunció Anton—. Entro a la cola. Sofia, tú.
Sofia tocó la pantalla. —Dentro.
—Mariana.
—Dentro —dijo ella, sin apartar la vista de su dispositivo.
Durante unos segundos, los indicadores giraron al mismo ritmo. Después, la pantalla de Anton parpadeó en rojo. Pop-up: Matchmaking failed. Connection lost.
—¿Qué? —Anton frunció el ceño—. Eso no puede pasar. La API está arriba.
—Yo sigo en cola —dijo Sofia, mostrando su pantalla.
—Yo estoy fuera —dijo Mariana—. Mi app se acaba de caer.
Hassan abrió los logs de staging. —Tenemos una cascada de excepciones de base de datos en matchmaking: Transaction aborted due to concurrent update.
—Lag de replicación —dijo Sofia, mirando métricas—. EU-West registró el join de Anton, pero antes de replicar a US-East, donde está Mariana, llegó su consulta. La máquina de estados quedó desincronizada.
—¡Pero desactivé el botón! —dijo Anton, alzando la voz—. El estado era “Searching”. ¿Cómo se desincroniza?
—Porque tu controlador de UI no maneja la latencia de red —dijo Mariana, girándole su tablet—. En local tienes 5 ms. En staging hay 120 ms entre regiones. Tu UI asumió transición instantánea. Mandó la solicitud, pero la desactivación del botón era asíncrona. En esa ventana de 120 ms se podía tocar dos veces. Y pasó.
Anton se quedó mirando el mensaje rojo, como si le hubieran faltado al respeto.
—Construí staging para encontrar justo estos huecos —dijo Hassan en voz baja—. En local, tu máquina te mintió. Ahora ves la verdad.
Anton miró a Stefan.
—No me mires a mí —dijo Stefan con una media sonrisa—. Yo solo soy el abogado. Aquí habla la evidencia.

Para la mañana del miércoles, Anton llevaba casi veinte horas atrapado en el mismo ciclo: cambiar, compilar, desplegar a staging, probar a mano con tres dispositivos, ver fallar, añadir más prints y repetir.
En su escritorio había botellas vacías de Club-Mate y notas arrugadas.
—No lo entiendo —murmuró Anton frente al terminal—. Metí debounce, metí un chequeo de estado de red, hasta rodeé toda la transición con un try-catch. Sigue cayéndose el 30% de las veces con tres regiones.
—Porque estás intentando arreglar una race condition adivinando —dijo Mariana con suavidad, acercando su silla—. Estás curando síntomas. Parches en UI. No la lógica de fondo.
—¡La máquina de estados está bien! —insistió Anton—. Es timing.
—Una máquina de estados que se rompe por timing no está bien —dijo Stefan desde la mampara—. Es frágil. Para volverla robusta tienes que separar timing de lógica.
Anton se dejó caer en la silla. —¿Cómo? No puedo simular lag multirregión en un unit test.
—No necesitas simular toda la red —dijo Mariana—. Solo mockear la interfaz de red. Inyectas una respuesta demorada y verificas qué hace la máquina cuando entra una segunda solicitud antes de que termine la primera.
Tocó su teclado. —Hagamos un test de caracterización. Uno solo. Describamos el fallo.
Anton miró el teclado y luego a Mariana. Estaba agotado. El bucle manual le estaba drenando la energía y faltaban tres horas para el sync con Lukas.
—Vale —dijo al fin—. Enséñame.
Mariana sonrió, sin triunfalismo. Abrió el IDE, creó un archivo de prueba nuevo y empezó a teclear.
—Primero, definimos el comportamiento esperado —dijo—. Si ya hay una solicitud en vuelo, el controlador de matchmaking debe ignorar nuevos join requests. Da igual si el botón está interactuable o no.
Escribió el nombre: Should_Ignore_Join_Request_When_Request_Is_In_Flight.
—Ahora tú —dijo, devolviéndole el teclado—. Setup: mock del servicio de red para devolver una tarea que complete en 500 milisegundos. Llama JoinMatchmaking dos veces seguidas. Y aserta que el servicio se invocó solo una vez.
Anton tomó el teclado. Al principio lento; después, con ritmo. El tecleo sonó más estable, menos nervioso.
Por primera vez en la semana no estaba escribiendo para presumir una funcionalidad. Estaba escribiendo para responder una pregunta.

—Pasó —susurró Anton.
Miró el check verde como si fuera un milagro.
—Obvio que pasó —dijo Mariana, riéndose—. Arreglamos el bug.
Con la prueba puesta, tardaron diez minutos en encontrar la race condition. Falló en la primera ejecución y dejó claro que la máquina estaba pasando a “Searching” antes de confirmar que el servidor había aceptado la solicitud.
Separaron estado de UI y estado de red, limpiaron la transición de forma síncrona y el fallo desapareció.
—Pasé dos días probando esto a mano —dijo Anton, negando con la cabeza—. Dos días compilando, desplegando y tocando tres tablets a la vez como un loco. Y lo encontramos en diez minutos con una prueba de treinta líneas.
—Ese es el costo de la velocidad —dijo Stefan—. Cuando te saltas una prueba para “ahorrar tiempo”, le pides horas prestadas a tu yo del futuro con interés del 500%. El lunes te sientes rápido. El miércoles estás en quiebra.
Anton volvió a mirar el check verde. —Es… raro, pero satisfactorio. Si alguien toca la lógica del botón el próximo mes, esto lo atrapa al instante. No tengo que vivir con miedo a que falle en silencio.
—Ese es el valor real de TDD —dijo Mariana, guardando su portátil—. No es pureza ni religión. Es paz mental. Sabes que el código está bien porque tienes una prueba que lo respalda.
Anton miró a Stefan. —Vale, abogado. Ganaste. No es teología. Es… muy buen desarrollo.
—Me sirve —sonrió Stefan—. Pero agradécele a Mariana. Ella fue la que se sentó contigo.
Anton miró a Mariana. —Gracias. Y… perdón por los comentarios de “teología”.
—No pasa nada —dijo Mariana, volviendo a su puesto—. Solo escribe los tests de la UI de torneos antes de la demo de mañana. Lukas sigue esperando verla.
—Ya estoy en eso —respondió Anton.
Esta vez, el sonido del teclado no era de pánico. Era de alguien que por fin sabía hacia dónde iba.

Lukas tocó la tablet y observó cómo la cola giraba, transicionaba y conectaba sin problemas a una partida multirregión simulada.
—Está estable —dijo, con sorpresa genuina—. Corremos cincuenta partidas simuladas en tres regiones esta tarde y no tuvimos ni un crash de base de datos ni un congelamiento de UI. ¿Cómo arreglaron tan rápido el tema de replicación?
—No arreglamos el retraso de replicación —respondió Katja, reclinándose—. El retraso es una restricción física de redes globales. No lo “eliminas”; diseñas el software para convivir con él.
Lukas parpadeó. —Entonces, ¿por qué ahora sí funciona?
—Porque dejamos de suponer inmediatez —dijo Katja—. Anton y Mariana escribieron pruebas que simulan el retraso y ajustaron la máquina de estados para manejarlo con gracia. La UI ya no asume una base de datos instantánea. Espera confirmación.
Lukas miró a Stefan. —¿Entonces staging sí sirvió?
—Hizo exactamente su trabajo —dijo Stefan—. Mostró dónde estaban mal los supuestos antes de que lo pagaran personas reales. Sin paridad de staging habríamos lanzado esto a producción y pasado el fin de semana en reuniones de emergencia.
Lukas asintió despacio. —¿Y el calendario? ¿Seguimos en línea para septiembre?
—Sí —dijo Katja—. Justamente porque ya no perdemos días en bucles manuales de depuración. El equipo escribe pruebas mientras construye. El día uno parece más lento; el día cinco vas más rápido porque entregas software, no parches.
Lukas se puso de pie y cerró su portátil. —Te lo admito, Katja. Cuando pediste seis semanas de “realismo operativo”, pensé que querías comprar tiempo. Pero esto… es la primera demo en seis meses que no parece sostenida con cinta.
—Porque no lo está —dijo Katja.
Salieron de la sala conversando sobre coordinación de marketing para Q3.
Stefan se quedó un minuto junto a la ventana. La tarde berlinesa estaba cálida, dorada, con luces reflejadas en el canal.
Afuera, Anton guardaba su mochila sin prisa. Ya no estaba encorvado sobre la pantalla con cara de alarma. Hablaba con Sofia, gesticulaba, se le escapaba una risa relajada.
La postura había cambiado.
El equipo ya no corría perseguido. Empezaba a gobernar su sistema, prueba por prueba.
Navigator — Katja Müller — 26 de junio de 2026, 18:12
Primera semana de la Operational Realism Initiative.
La presión por entregar no desapareció porque el consejo aprobara presupuesto. El lunes, Anton intentó atajar y saltarse pruebas para sacar rápido la UI de matchmaking de torneos.
El nuevo staging hizo exactamente lo que necesitábamos: expuso sus supuestos de inmediato. Las réplicas multirregión introdujeron latencia que su máquina local ocultaba, y la UI se rompió con solicitudes concurrentes.
El punto de inflexión fue el miércoles, cuando Mariana se sentó con él y escribieron una prueba de caracterización para aislar la race condition. Con la prueba puesta, encontraron y corrigieron el fallo en diez minutos.
La actitud de Anton frente a TDD pasó de “teología” a “buen desarrollo”. Lo vio en carne propia: saltarse pruebas no ahorra tiempo, solo mueve la fricción a una fase más cara.
Señales de Navigator esta semana:
- El repositorio de Unity recibió sus primeras pruebas unitarias automatizadas de UI.
- La estabilidad de staging llegó al 99,8% bajo pruebas de carga simulada.
- Por segunda semana consecutiva no se registró trabajo de fin de semana para ningún perfil de desarrollo.
- Las sesiones de pairing entre backend y Unity subieron un 40%.
Estamos construyendo sobre suelo firme. La pista se está pavimentando y el equipo vuelve a conducir con control.
La próxima semana empezamos pruebas de carga con 150.000 personas usuarias simuladas. Ahí empieza la prueba real de las réplicas.