====== 08 - TDD ======
**TDD** (*Test-Driven Development*, desarrollo dirigido por pruebas) invierte el orden habitual: la prueba se escribe **antes** que el código que la hace pasar. El ciclo tiene tres pasos, repetidos en bucles cortos.
===== 1. El ciclo =====
^ Paso ^ Qué se hace ^ Resultado ^
| **Rojo** | Escribir una prueba del comportamiento nuevo y ejecutarla | Falla: el código no existe aún |
| **Verde** | Escribir el código **mínimo** que hace pasar la prueba | Todas las pruebas pasan |
| **Refactor** | Mejorar el diseño sin cambiar el comportamiento | Las pruebas siguen pasando |
@startuml
(*) --> "Escribir prueba (rojo)"
"Escribir prueba (rojo)" --> "Ejecutar y verla fallar"
"Ejecutar y verla fallar" --> "Escribir código mínimo (verde)"
"Escribir código mínimo (verde)" --> "Ejecutar y verla pasar"
"Ejecutar y verla pasar" --> "Refactorizar"
"Refactorizar" --> "Ejecutar pruebas"
"Ejecutar pruebas" --> "Escribir prueba (rojo)" : siguiente comportamiento
"Ejecutar pruebas" --> (*)
@enduml
===== 2. Ejemplo paso a paso =====
**Rojo:** la prueba describe el comportamiento que falta:
@Test
void refusesExpiredProduct() {
Inventory inventory = new Inventory();
assertThrows(ExpiredProductException.class,
() -> inventory.add("MILK-1", LocalDate.now().minusDays(1)));
}
Ejecutarla falla: ''Inventory'' no tiene ese método o no lanza la excepción.
**Verde:** el código mínimo para pasarla:
public void add(String code, LocalDate expiry) {
if (expiry.isBefore(LocalDate.now())) {
throw new ExpiredProductException();
}
/* registrar el producto */
}
**Refactor:** mejorar nombres, extraer una constante, simplificar. Las pruebas protegen cada cambio.
===== 3. Por qué funciona =====
* **Diseño guiado por uso:** la prueba obliga a pensar primero en la interfaz del código, desde el punto de vista de quien lo consume.
* **Red de seguridad continua:** cada comportamiento queda protegido antes de que exista el código final.
* **Feedback inmediato:** segundos entre el error y su corrección, no horas.
* **Cobertura real:** no queda código sin probar porque cada línea nace de una prueba.
===== 4. Refactorización =====
**Refactorizar** es cambiar la estructura del código sin cambiar su comportamiento: extraer un método, renombrar, eliminar duplicación. Es el tercer paso del ciclo y depende de las pruebas: sin ellas, un refactor puede introducir errores invisibles.
En la práctica, el asistente de IA puede proponer los cambios de refactorización; las pruebas son quienes comprueban que el comportamiento no ha cambiado.
===== 5. Cuándo conviene =====
^ Encaja bien ^ Encaja peor ^
| Lógica de negocio con reglas claras | Código de interfaz, configuración |
| Algoritmos y cálculos | Exploración y prototipos |
| Corrección de errores: la prueba que reproduce el bug primero | Código efímero que se descartará |
TDD no aumenta el número de pruebas escritas: las escribe antes, en pasos pequeños. El resultado es un código con la misma cobertura pero diseñado desde su uso.