TDD con IA: valida el código autogenerado antes de mergear
Revisé una Pull Request generada por un asistente de IA hace un par de semanas.
El autor de la PR estaba fascinado: "Mira qué limpio quedó el algoritmo de descuentos por volumen. La IA lo escribió en 15 segundos".
El código tenía nombres impecables, comentarios en JSDoc y tipado de TypeScript sin un solo error. Le faltaba lo único que sostiene el TDD con IA: tests.
Escribí una prueba unitaria pasando una compra con descuento de cliente VIP combinado con un cupón del 100%. El sistema devolvió un saldo negativo donde la tienda terminaba debiéndole dinero al comprador.
El modelo de IA no tenía mala intención: simplemente no sabía qué reglas de negocio proteger porque nadie se las había formulado como una prueba ejecutable.
En la era de los asistentes de código, Test-Driven Development (TDD) no está muerto; es más indispensable que nunca. Aquí tienes el flujo exacto para combinar TDD con IA.
El nuevo ciclo Red-Green-Refactor con Agentes de Código
El ciclo clásico de TDD se transforma radicalmente cuando tienes un agente a tu lado:
┌─────────────────────────────────────────────────────────────┐
│ FLUJO TDD POTENCIADO POR IA │
│ │
│ 1. HUMANO (Diseño) ──> Escribe el Test Unitario (ROJO) │
│ │ │
│ ▼ │
│ 2. AGENTE (Código) ──> Genera la Implementación (VERDE) │
│ │ │
│ ▼ │
│ 3. DÚO (Calidad) ──> Refactoriza con Seguridad │
└─────────────────────────────────────────────────────────────┘
En lugar de delegar el diseño a ciegas, el desarrollador asume el rol de arquitecto: define el contrato y los casos de borde en una prueba. El agente asume el trabajo pesado de implementar la sintaxis.
Ejemplo Práctico: Implementando una lógica de negocio paso a paso
Paso 1: Escribe el test en fallo (Rojo con Vitest)
Antes de crear el archivo de lógica, defines el comportamiento esperado:
// src/pricing/discount-calculator.spec.ts
import { describe, it, expect } from 39;vitest39;;
import { calculateTotalWithDiscounts } from 39;./discount-calculator39;;
describe(39;calculateTotalWithDiscounts39;, () => {
it(39;aplica descuento por volumen del 10% en compras mayores a $10039;, () => {
const total = calculateTotalWithDiscounts({ subtotal: 150, isVip: false, couponPercent: 0 });
expect(total).toBe(135);
});
it(39;nunca devuelve un total negativo incluso con cupones acumulados39;, () => {
const total = calculateTotalWithDiscounts({ subtotal: 50, isVip: true, couponPercent: 120 });
expect(total).toBe(0); // Regla de negocio crítica
});
});
Al ejecutar bun test, el test falla inmediatamente porque la función ni siquiera existe.
Paso 2: Pasa el test al agente como contrato ejecutable
Invocas a tu agente de IA en la terminal con una instrucción cerrada:
claude "Lee discount-calculator.spec.ts. Crea el archivo discount-calculator.ts con la implementación mínima necesaria para que los tests pasen en verde. Prohibido modificar el archivo de tests."
Paso 3: El agente genera el código para poner el test en verde
El agente analiza la firma de tipos esperada y las aserciones, generando la lógica requerida:
// src/pricing/discount-calculator.ts
export interface PricingOptions {
subtotal: number;
isVip: boolean;
couponPercent: number;
}
export function calculateTotalWithDiscounts(options: PricingOptions): number {
const { subtotal, isVip, couponPercent } = options;
let discount = 0;
if (subtotal > 100) discount += subtotal * 0.10;
if (isVip) discount += subtotal * 0.05;
if (couponPercent > 0) discount += subtotal * (couponPercent / 100);
const finalTotal = subtotal - discount;
return Math.max(0, finalTotal); // Respeta el caso de borde
}
El agente ejecuta el test runner de forma autónoma y confirma que la suite está en verde.
Por qué este flujo recorta los bugs que llegan a producción
- Elimina la alucinación de requisitos: El modelo no tiene margen para inventar parámetros porque el test ya definió la interfaz y los valores esperados.
- Aislamiento de contexto: No necesitas explicar la arquitectura completa de tu empresa; solo entregas el archivo de prueba.
- Refactorización sin miedo: Si mañana quieres optimizar el rendimiento del algoritmo, puedes pedirle a la IA que lo refactorice sabiendo que cualquier regresión encenderá una alarma roja de inmediato.
Que quede claro: esto no lleva los bugs a cero. Ningún flujo lo hace. Lo que hace es mover el error de "se descubre en producción tres semanas después" a "se descubre en el segundo en que el agente ejecuta la suite". Los fallos que se te escapan siguen siendo los casos que no se te ocurrió escribir.
Para que el ciclo funcione, la suite tiene que correr en milisegundos, no en minutos: aquí tienes cómo montar pruebas unitarias ultrarrápidas con Vitest. Si el agente tarda 90 segundos en saber si acertó, el bucle rojo-verde deja de ser un bucle.
En el curso de Testing en Angular con Jest y Testing Library enseñamos a estructurar suites de pruebas profesionales para frontend y backend preparadas para integrarse con flujos automatizados de CI/CD.
Este enfoque de validación es también uno de los pilares centrales de nuestro libro de Spec-Driven Development (SDD).
Para descargar pipelines de automatización con Vitest y plantillas de pruebas para agentes, visita Dominicode Labs.
Qué hacer hoy con esto
Para la próxima función o endpoint que vayas a programar:
- No escribas la implementación.
- Escribe primero dos tests unitarios en Vitest: uno para el caso feliz y otro para el caso borde más peligroso.
- Pásaselo a tu asistente de IA y pídele que escriba la función que los cumpla.
Comprobarás dos cosas: que el primer diff llega mucho más cerca de lo que querías, y que las rondas de corrección se reducen a una o dos.
Si además quieres que el agente derive los tests de una especificación en vez de escribirlos tú a mano, ese es el siguiente escalón: TDD y Spec-First aplicados al desarrollo con IA.
Preguntas frecuentes
¿Por qué TDD es especialmente útil al programar con IA?
Porque un test unitario actúa como una especificación matemática ejecutable. Los modelos de lenguaje responden con muchísima mayor precisión cuando tienen un criterio binario de éxito (el test pasa o falla) que cuando reciben instrucciones en lenguaje natural ambiguo.
¿Se debe permitir que la IA modifique los tests unitarios?
No. Los tests unitarios deben ser diseñados y aprobados por el desarrollador. Si permites que la IA modifique los tests para que "pasen en verde", corres el riesgo de que relaje las aserciones y oculte errores de negocio.
¿Qué framework de tests es más rápido para iterar con agentes de IA?
Vitest es actualmente la opción más recomendada en el ecosistema TypeScript por su velocidad de arranque instantánea, compatibilidad nativa con ESM y excelente integración en terminales CLI.
¿Puede la IA escribir también los tests en lugar del desarrollador?
Puede escribir el andamiaje y los casos evidentes, pero no debe decidir qué se protege. Si el modelo escribe los tests y la implementación, ambos comparten el mismo malentendido y la suite en verde no demuestra nada. El desarrollador define los casos de borde; la IA rellena el resto.
¿Cuántos tests hacen falta antes de pasarle la tarea al agente?
Dos suelen bastar para arrancar: el caso feliz y el caso de borde más caro si falla. Con eso el agente ya tiene una interfaz cerrada y un criterio binario de éxito. Ampliar la cobertura tiene más sentido después, cuando ya sabes por dónde se rompe la implementación real.
Por Bezael Pérez — Developer senior con más de 15 años de experiencia y fundador de Dominicode.
