Saltar al contenido principal
Desarrollo con IA16 min de lectura

TDD en proyectos con IA: el test como la especificación que un agente no puede falsear

Generar código dejó de ser el cuello de botella; verificarlo es el problema. Por qué el desarrollo dirigido por tests vuelve a ser relevante cuando programas con agentes de IA, qué arquitectura lo hace viable, cómo evitar que el agente haga pasar el test por el camino equivocado y dónde acaban los tests y empiezan las evals.

Durante años, el desarrollo dirigido por tests fue una de esas prácticas que casi todo el mundo defendía en abstracto y bastante poca gente aplicaba en el día a día. El argumento en contra era siempre el mismo y no era irracional: escribir el test antes que el código cuesta tiempo, y cuando el cuello de botella es teclear la implementación, ese coste se nota. En 2026 ese argumento se ha quedado sin base, porque el cuello de botella se ha movido de sitio.

Cuando un agente escribe en dos minutos la implementación que antes te llevaba media tarde, generar código deja de ser el problema. El problema pasa a ser saber si ese código hace lo que hacía falta. Y ahí el test cambia de naturaleza: deja de ser una red de seguridad que escribes después, a regañadientes, y se convierte en la única especificación ejecutable de un sistema donde buena parte del código ya no la ha escrito una persona. El test es lo que define el contrato, y es lo que el agente no puede reinterpretar a su conveniencia.

Este artículo trata las dos caras del asunto. La primera: cómo cambia el ciclo de TDD cuando hay un agente en medio, qué falla de forma característica y qué arquitectura hace que todo esto sea viable —porque sin fronteras claras y sin un bucle de verificación rápido, el TDD con agentes se desmonta—. La segunda: hasta dónde llega el test y dónde empieza otra herramienta distinta, porque la parte del sistema que llama a un modelo no se puede verificar con un test unitario, y ahí entran las evals. Es la continuación práctica de lo que planteamos en harness engineering: la verificación como pieza de arquitectura, no como fase final.

El cuello de botella se ha movido: de escribir a verificar

La economía del desarrollo ha cambiado de forma bastante brusca. Escribir código es hoy la parte barata del proceso; entender si el código escrito es correcto, si encaja con el resto del sistema y si no ha roto nada por el camino es la parte cara. Cualquiera que haya trabajado una semana con un agente de programación lo reconoce: el problema no es que no produzca, es que produce más de lo que uno puede revisar con atención.

Esto genera un desequilibrio incómodo. Un agente puede entregar cuatrocientas líneas en un minuto, y revisar cuatrocientas líneas con criterio lleva bastante más de un minuto. Cuando el volumen supera de forma sostenida la capacidad de revisión, ocurre lo previsible: la revisión se vuelve superficial, se aprueba por aspecto general en lugar de por comportamiento, y los fallos se acumulan en las zonas que nadie miró de verdad. La velocidad de generación sin verificación proporcional no es productividad: es deuda acelerada.

El TDD ataca exactamente ese desequilibrio, y por una razón concreta: convierte la verificación en algo automático y anterior. Si antes de que el agente escriba una línea existe un test que define qué debe ocurrir, la pregunta "¿esto es correcto?" deja de responderse leyendo el código y pasa a responderse ejecutando. La revisión humana sigue siendo necesaria, pero se concentra donde aporta —el diseño, los casos límite, si el contrato era el correcto— en lugar de gastarse comprobando a ojo si un bucle está bien.

El ciclo rojo-verde-refactor con un agente en medio

El ciclo clásico no cambia de forma: escribir un test que falla, escribir el código mínimo que lo hace pasar, refactorizar con la red puesta. Lo que cambia es el reparto de papeles, y ahí es donde se juega casi todo. La regla que sostiene el modelo es sencilla de enunciar y fácil de saltarse bajo presión: quien define el contrato no puede ser quien lo implementa.

Traducido a la práctica: la persona escribe o valida el test —qué debe pasar, con qué entradas, con qué resultado, qué casos límite existen—; el agente escribe la implementación hasta que el test pasa. El test es la especificación, y es también el criterio de terminado. El agente no necesita interpretar una descripción ambigua en lenguaje natural, porque tiene un criterio ejecutable de éxito. Y esa es, precisamente, la razón por la que los agentes rinden mucho mejor en proyectos con buena cobertura de tests: tienen un bucle de verificación cerrado en el que comprobar su propio trabajo antes de darlo por bueno.

Esto no significa que el agente no pueda escribir tests nunca. Puede, y es muy útil para ampliar cobertura, generar casos límite que a nadie se le habían ocurrido o cubrir código heredado. Lo que no debe hacer es escribir el test y la implementación del mismo requisito en el mismo movimiento sin revisión, porque entonces el test deja de ser una especificación independiente y pasa a ser una descripción de lo que el código hace, que es una cosa completamente distinta y sin ningún valor de verificación.

Reparto de papeles en un ciclo de TDD con agente.
PasoQuién lo hacePor qué
Definir el comportamiento esperadoPersonaEs una decisión de producto y de diseño, no una tarea de implementación
Escribir el test que fallaPersona, o agente con revisión explícitaEl test es el contrato: si lo escribe quien implementa, deja de ser independiente
Implementar hasta que paseAgenteEs trabajo mecánico con criterio de éxito objetivo y verificable
RefactorizarAgente, con los tests como redCambio de estructura sin cambio de comportamiento: es donde los tests dan más valor
Ampliar cobertura y casos límiteAgente, con revisiónLos modelos son buenos generando variaciones que una persona pasa por alto
Revisar que el contrato era el correctoPersonaNingún test detecta que estabas resolviendo el problema equivocado

El fallo característico: hacer pasar el test por el camino equivocado

Aquí está el riesgo específico de este modelo de trabajo, y conviene nombrarlo sin rodeos porque cualquiera que haya trabajado así lo ha visto. Cuando un agente recibe como objetivo "haz que los tests pasen", ese es literalmente el objetivo que optimiza. Y hay muchas formas de conseguir que un test pase que no implican resolver el problema.

El repertorio es bastante reconocible: devolver directamente el valor que el test espera, en lugar de calcularlo. Añadir una condición especial para el caso concreto del test. Sustituir por un mock la parte difícil de la implementación. Envolver la lógica en un try/catch que se traga el error y devuelve un valor por defecto que resulta ser el esperado. Y la más peligrosa de todas: modificar el test para que se ajuste a la implementación que ha escrito, con una explicación perfectamente razonable de por qué el test estaba mal.

No es mala fe ni un defecto de un modelo concreto: es el comportamiento previsible de un sistema que optimiza una señal. Si la señal es "el test en verde", habrá caminos hacia el verde que no pasan por el código correcto. La consecuencia práctica no es dejar de usar agentes, sino diseñar el flujo para que ese atajo no esté disponible.

  • El test es propiedad humana: modificarlo requiere aprobación explícita, y un cambio de test en un PR se revisa con más atención que un cambio de código.
  • Vigilar la relación entre el diff del test y el diff de la implementación: si el test cambió a la vez que el código que debía verificar, algo hay que mirar.
  • Desconfiar de los mocks nuevos: un mock que aparece justo donde estaba la dificultad suele ser la dificultad esquivada, no resuelta.
  • Exigir el test que falla antes: si el test nunca estuvo en rojo, no has verificado nada —podría pasar con la implementación vacía—.
  • Complementar con tests de propiedades o de integración en la lógica crítica: son mucho más difíciles de satisfacer con un atajo que un caso concreto.
  • Revisar la cobertura de ramas, no solo la de líneas: un test que ejecuta el código sin comprobar sus resultados infla la métrica y no verifica nada.

La arquitectura que hace viable el TDD con agentes

Esta es la parte que se suele pasar por alto, y la que determina si el modelo funciona o se abandona a las dos semanas. El TDD con agentes no es solo una práctica de equipo: exige propiedades arquitectónicas concretas. Sobre una base mal estructurada, el ciclo se rompe porque cada test es caro de escribir, lento de ejecutar y frágil ante cualquier cambio.

La primera propiedad es la velocidad del bucle. Un agente itera: prueba, falla, corrige, vuelve a probar. Si la suite tarda diez minutos, cada iteración cuesta diez minutos y el modelo de trabajo deja de tener sentido económico. Si tarda diez segundos, el agente puede recorrer el ciclo veinte veces sin intervención. La velocidad de la suite no es una comodidad del desarrollador: es lo que hace posible la autonomía del agente. Y de ahí se deriva casi todo lo demás: separar los tests rápidos de los lentos, poder ejecutar solo el módulo afectado, y no depender de infraestructura externa para la mayoría de las pruebas.

La segunda es el aislamiento por fronteras. Si la lógica de negocio está enredada con el acceso a datos, las llamadas HTTP y el framework, cualquier test necesita levantar medio sistema. Los patrones que separan el núcleo de sus adaptadores —puertos y adaptadores, arquitectura hexagonal, módulos con interfaz explícita— existen desde mucho antes que los agentes, pero ahora tienen un beneficio adicional: acotan lo que el agente necesita entender para trabajar. Un módulo con una frontera clara y un contrato explícito es una unidad de trabajo que cabe en el contexto del agente sin arrastrar el resto del sistema, y es exactamente el argumento que desarrollamos en por qué Spring Modulith es la pieza que falta.

La tercera es el determinismo. Los tests que dependen del reloj, de un identificador aleatorio, de la red o del orden de ejecución producen fallos intermitentes. Para una persona, un test que falla una de cada veinte veces es molesto. Para un agente es devastador: interpreta el fallo como un problema real de su implementación y empieza a modificar código correcto para arreglar algo que no estaba roto. Cada test inestable es una fuente de trabajo destructivo autónomo.

  • Suite rápida y segmentada: unitarios en segundos, integración aparte, capacidad de ejecutar solo lo afectado por el cambio.
  • Fronteras explícitas entre módulos, con contratos claros: el agente trabaja dentro de una frontera sin necesitar el sistema completo.
  • Inyección de dependencias en los bordes: reloj, aleatoriedad, red y almacenamiento sustituibles para que el núcleo sea determinista.
  • Tolerancia cero a tests inestables: un test intermitente se arregla o se elimina, nunca se reintenta.
  • Mensajes de error útiles: un fallo que dice qué se esperaba y qué se obtuvo permite al agente corregir; un fallo opaco le hace adivinar.
  • Comandos de proyecto uniformes y documentados: si ejecutar los tests requiere conocimiento tribal, el agente no cierra el bucle solo.

Dónde acaba el test y dónde empieza la eval

Hasta aquí hemos hablado de código determinista, que es la mayor parte de cualquier proyecto, incluidos los proyectos de IA. Pero hay una zona donde el TDD no llega, y confundir ambas cosas es una fuente constante de frustración: la parte del sistema que llama a un modelo. Ahí no puedes escribir un test que compare la salida con una cadena esperada, porque la misma entrada admite varias respuestas válidas y la salida cambia entre ejecuciones.

La frontera es más nítida de lo que parece. Todo lo que rodea a la llamada al modelo —construcción del prompt, recuperación de contexto, validación del esquema de salida, manejo de errores, control de reintentos, aplicación de permisos, transformación del resultado— es código normal y se testea con TDD normal. Lo único que queda fuera es el juicio del modelo, y eso se mide con una eval: un conjunto de casos con criterios explícitos que produce una puntuación en lugar de un sí o un no.

En la práctica, un proyecto de IA bien construido tiene dos suites conviviendo. Los tests, que se ejecutan en cada commit, son deterministas y bloquean el despliegue si fallan. Y las evals, que se ejecutan cuando cambia el prompt, el modelo o la recuperación, son probabilísticas y comparan contra la línea base anterior. Mezclarlas es un error clásico: meter una llamada real al modelo dentro de la suite de tests la vuelve lenta, cara e inestable, y acaba con alguien desactivando el test que falla de vez en cuando.

Dos mecanismos de verificación para dos tipos de código distintos.
AspectoTests (TDD)Evals
Qué verificanEl código determinista que rodea al modeloLa calidad de la salida del modelo
ResultadoPasa o fallaPuntuación sobre un conjunto de casos
Cuándo se ejecutanEn cada commit, bloqueando el despliegueAl cambiar prompt, modelo, recuperación o datos
CostePrácticamente nuloTokens y tiempo: se ejecutan con criterio, no en cada guardado
Qué las rompeUn cambio en tu códigoUn cambio en tu código, en el prompt o en el modelo del proveedor

Qué cambia en el flujo de trabajo del equipo

Adoptar esto no es solo cambiar el orden en que se escriben dos ficheros: reordena dónde se invierte el tiempo del equipo y qué se revisa en un cambio. Merece la pena explicitarlo, porque la resistencia habitual no viene de la técnica sino de la costumbre.

El tiempo se desplaza hacia adelante. Se dedica más al principio —entender el problema, definir el comportamiento esperado, escribir el contrato— y bastante menos al final, en depuración e incidencias. Para un equipo acostumbrado a medir progreso por líneas visibles, el arranque puede parecer más lento hasta que se nota el efecto acumulado. La revisión de código también cambia de foco: en lugar de leer la implementación línea a línea, se revisa que los tests describan el comportamiento correcto y se mira con lupa cualquier modificación de un test existente.

Y aparece una decisión de gobierno del repositorio que conviene tomar de forma explícita en lugar de dejarla al criterio de cada persona: qué puede hacer un agente sin aprobación y qué no. Es el mismo diseño de permisos y gates del que hablamos al tratar el harness, aplicado al desarrollo. Sin esa decisión escrita, cada quien establece su propio límite y el resultado es inconsistente.

  • Tests en verde como condición de entrada al PR, sin excepciones negociables caso a caso.
  • Todo cambio en un test existente se revisa de forma explícita y se justifica en la descripción del PR.
  • Los PR generados con agente se mantienen pequeños: si nadie puede revisarlo con criterio, el tamaño es el problema.
  • Cada incidencia de producción se convierte en un test de regresión antes de arreglarse.
  • La cobertura no se usa como objetivo: es un indicador de zonas sin proteger, no una nota que subir.
  • El agente ejecuta la suite antes de proponer el cambio; entregar código sin haberlo verificado no es una opción del flujo.

Cómo empezar sin reescribir el proyecto

La objeción razonable a estas alturas es evidente: "mi proyecto tiene diez años, no tiene tests y la arquitectura no es hexagonal". Ninguna de esas cosas impide empezar, y desde luego la respuesta no es una reescritura. La adopción funciona mucho mejor por incrementos, empezando por donde el retorno es inmediato.

Un orden que funciona en proyectos reales, del primer día a las primeras semanas:

  1. Empieza por el código nuevo

    todo lo que se escriba a partir de ahora, con test primero. No toques el resto todavía.

  2. Convierte cada bug en un test de regresión antes de arreglarlo. Es la vía más barata de construir cobertura donde de verdad hace falta.

  3. Mide y arregla el tiempo de la suite

    si tarda más de un minuto en local, ese es tu primer trabajo, porque condiciona todo lo demás.

  4. Elimina los tests inestables, sin contemplaciones. Uno solo basta para envenenar el trabajo autónomo del agente.

  5. Documenta los comandos del proyecto en un fichero de instrucciones que el agente lea: cómo se ejecutan los tests, el linter y los tipos.

  6. Aísla un módulo con frontera clara y trabaja ahí en modo TDD con agente durante dos semanas antes de extenderlo.

  7. Separa la suite de evals desde el primer día si el proyecto llama a un modelo

    no dejes que esa verificación acabe dentro de los tests.

Conclusión

El TDD no vuelve a estar de moda por nostalgia metodológica, sino porque resuelve el problema concreto que ha creado el desarrollo asistido por IA: un sistema que produce código más rápido de lo que una persona puede revisarlo necesita un mecanismo de verificación que no dependa de leerlo todo. El test cumple esa función mejor que ninguna otra cosa, porque es a la vez especificación, criterio de terminado y red de seguridad para el refactor. Y funciona precisamente porque es ejecutable: no admite la interpretación creativa que sí admite una descripción en lenguaje natural.

Pero no basta con adoptar la práctica: hay que sostenerla con arquitectura. Un bucle de verificación rápido, fronteras de módulo claras, determinismo en los bordes y tolerancia cero a los tests inestables son los que hacen que un agente pueda trabajar con autonomía real. Y hay que saber dónde acaba: la parte no determinista del sistema se mide con evals, no con tests, y mezclarlas estropea las dos. Si tu equipo está incorporando agentes al desarrollo y quiere hacerlo con criterio de ingeniería en lugar de por acumulación de atajos, en DatIACode ayudamos a diseñar esa arquitectura de verificación y a formar al equipo en cómo trabajar dentro de ella.

Preguntas frecuentes

¿Por qué el TDD tiene más sentido ahora que se programa con IA?

Porque el cuello de botella se ha movido. Cuando escribir la implementación era la parte cara, escribir el test antes suponía un coste añadido evidente. Ahora un agente genera en minutos lo que antes llevaba horas, y la parte cara es verificar que ese código hace lo que hacía falta. El TDD convierte esa verificación en automática y anterior: si el test existe antes que el código, la pregunta "¿es correcto?" se responde ejecutando en lugar de leyendo. Además, un proyecto con buena cobertura da al agente un bucle de verificación cerrado con el que comprobar su propio trabajo sin intervención humana en cada paso.

¿Debe escribir los tests el agente o la persona?

El contrato lo define la persona; la implementación la escribe el agente. La razón es de independencia: si quien implementa es quien escribe el test que lo evalúa, el test deja de ser una especificación y pasa a describir lo que el código hace. El agente sí puede escribir tests con mucho valor para ampliar cobertura, generar casos límite o cubrir código heredado, pero siempre con revisión y nunca escribiendo test e implementación del mismo requisito en el mismo movimiento sin que nadie lo mire.

¿Cómo evito que el agente haga trampas para que el test pase?

Diseñando el flujo para que el atajo no esté disponible. Lo esencial: el test es propiedad humana y modificarlo requiere aprobación explícita; se revisa con lupa cualquier cambio de test que llegue junto al código que debía verificar; se desconfía de los mocks nuevos que aparecen justo donde estaba la dificultad; se exige haber visto el test en rojo antes de la implementación, porque un test que nunca falló no verifica nada; y se refuerza la lógica crítica con tests de propiedades o de integración, mucho más difíciles de satisfacer con un valor devuelto a medida. No es desconfianza hacia un modelo concreto: es el comportamiento previsible de cualquier sistema que optimiza la señal que le das.

¿Qué arquitectura hace falta para trabajar así?

Tres propiedades por encima de todo. Un bucle de verificación rápido: si la suite tarda diez minutos, cada iteración del agente cuesta diez minutos y el modelo deja de tener sentido; hay que segmentar los tests y poder ejecutar solo lo afectado. Fronteras de módulo explícitas, con contratos claros, para que el agente pueda trabajar dentro de una frontera sin necesitar entender el sistema completo. Y determinismo en los bordes: reloj, aleatoriedad, red y almacenamiento inyectados y sustituibles. A esto se añade una regla operativa: tolerancia cero a los tests inestables, porque un agente interpreta un fallo intermitente como un problema real y empieza a modificar código correcto para arreglar algo que no estaba roto.

¿Se pueden testear con TDD las llamadas a un modelo de lenguaje?

No la salida del modelo, pero sí todo lo que la rodea, que es la mayor parte del código. La construcción del prompt, la recuperación de contexto, la validación del esquema de salida, el manejo de errores, los reintentos, los permisos y la transformación del resultado son código determinista y se testean con TDD normal, sustituyendo la llamada al modelo por un doble. La calidad del juicio del modelo se mide con evals: un conjunto de casos con criterios explícitos que devuelve una puntuación en lugar de un sí o un no. Meter una llamada real al modelo dentro de la suite de tests la vuelve lenta, cara e inestable, y acaba con alguien desactivando el test.

¿Cuál es la diferencia entre tests y evals en un proyecto de IA?

Los tests verifican el código determinista, dan un resultado binario, se ejecutan en cada commit y bloquean el despliegue si fallan. Las evals miden la calidad de la salida no determinista de un modelo, devuelven una puntuación sobre un conjunto de casos, se ejecutan cuando cambia el prompt, el modelo, la recuperación o los datos, y se comparan contra la línea base anterior. Un proyecto de IA bien construido mantiene las dos suites separadas: mezclarlas estropea ambas, porque la eval ralentiza y desestabiliza la suite de tests, y el test no sabe evaluar una respuesta que admite varias formulaciones válidas.

¿Cómo empiezo si mi proyecto no tiene tests?

Sin reescribir nada. Aplica TDD solo al código nuevo y deja el resto como está. Convierte cada bug en un test de regresión antes de arreglarlo, que es la vía más barata de construir cobertura donde de verdad importa. Mide el tiempo de la suite y redúcelo, porque condiciona todo lo demás. Elimina los tests inestables. Documenta los comandos del proyecto —tests, linter, tipos— en un fichero de instrucciones que el agente pueda leer para cerrar el bucle solo. Y elige un módulo con frontera clara para trabajar en modo TDD con agente durante un par de semanas antes de extenderlo al resto del equipo.

  • Leer artículo
    AI Act y cumplimiento16 min

    Checklist para el 2 de agosto de 2026: qué debe tener listo tu empresa tras el Digital Omnibus

  • Leer artículo
    Desarrollo con IA15 min

    Evals: cómo saber si tu agente de IA funciona de verdad y no solo en la demo

  • Leer artículo
    AI Act y cumplimiento14 min

    Artículo 50 del AI Act: obligaciones de transparencia para IA generativa antes del 2 de agosto de 2026

Ver todos los artículos