Clase 14 — Tema 8B: Test Driven Development (TDD) en Profundidad
Resumen Ejecutivo
Segunda parte del Tema 8. Se desarrolla en detalle el ciclo Red-Green-Refactor del TDD, se justifica por qué es fundamentalmente una técnica de diseño más que de testing, se explica el patrón Arrange/Act/Assert con ejemplos en C# y Java, y se introduce la evolución hacia ATDD y BDD. Se presenta también la actividad grupal final: proyecto React con Cypress, con entrega obligatoria antes del cierre del período.
Conceptos Clave
- TDD (Test-Driven Development): escribir la prueba antes de implementar el código. Ciclo: Rojo → Verde → Refactorizar. ⚠️ EXAMEN
- Red-Green-Refactor: (1) escribe un test que falla (rojo), (2) implementa el mínimo código para que pase (verde), (3) limpia y mejora sin romper el test.
- TDD como técnica de diseño: al pensar cómo probar un método antes de escribirlo, se reflexiona sobre su API, parámetros, valores extremos y desacoplamiento.
- Arrange / Act / Assert (AAA): estructura recomendada para cada test unitario. ⚠️ EXAMEN
- ATDD (Acceptance TDD): las pruebas de aceptación (escritas con el cliente) guían el desarrollo de cada historia de usuario.
- BDD (Behavior-Driven Development): las pruebas se expresan en lenguaje casi natural (Gherkin/Cucumber). Facilita la colaboración con stakeholders no técnicos.
- Cypress: framework de pruebas end-to-end para aplicaciones web. Se usará en la actividad grupal.
- Cobertura de pruebas: porcentaje de código ejercitado por los tests. El TDD la aumenta automáticamente al exigir escribir el test antes.
Desarrollo del Temario
1. El ciclo Red-Green-Refactor
[1] Escribe una prueba → falla (RED)
[2] Implementa lo mínimo para que pase (GREEN)
[3] Refactoriza el código sin romper la prueba (REFACTOR)
→ vuelve a [1] con la siguiente funcionalidad
Ventajas principales: - Mejora el diseño del código (desacoplamiento, métodos más pequeños) - Aumenta la cobertura de pruebas - Detecta errores en el momento en que se introducen - Reduce el tamaño del código (nos centramos en lo necesario) - Produce requisitos ejecutables: el test documenta qué debe hacer el código
Comparativa con el enfoque tradicional:
| Tradicional | TDD |
|---|---|
| Pruebas al final, si queda tiempo | Prueba antes de codificar |
| Las pruebas documentan lo que se hizo | Las pruebas especifican lo que debe hacerse |
| Bugs detectados tarde (coste exponencial) | Bugs detectados en el ciclo |
2. Patrón Arrange / Act / Assert (AAA)
Cada método de prueba sigue tres fases:
// ARRANGE: preparar el estado inicial
var account = new Account("usuario", balance: 1000);
var amountToWithdraw = 200;
var expectedBalance = 800;
// ACT: invocar el método bajo prueba
var actualBalance = account.Withdraw(amountToWithdraw);
// ASSERT: verificar el resultado
Assert.AreEqual(expectedBalance, actualBalance);
// Ejemplo en Java con JUnit
@Test
void testSuma() {
// Arrange
int a = 2, b = 2;
// Act
int result = Calculator.sum(a, b);
// Assert
assertEquals(4, result);
}
El test también diseña la clase: al escribirlo, decidimos que Calculadora.sumar es un método estático, qué parámetros acepta y qué devuelve.
3. Quién escribe las pruebas
| Contexto | Quién prueba |
|---|---|
| TDD estricto (pruebas unitarias) | El propio desarrollador |
| XP con rol de tester | Persona diferente al implementador (más objetividad) |
| ATDD / BDD | El analista/cliente junto al equipo |
La ventaja de separar roles: quien no implementó el código puede encontrar edge cases que el autor pasa por alto (efecto "ceguera del padre").
4. Evolución: ATDD → BDD
TDD → ATDD → BDD
- ATDD: las historias de usuario se expresan como pruebas de aceptación escritas en colaboración con el cliente antes de codificar.
- BDD (Behavior-Driven Development): usa Gherkin (lenguaje Given/When/Then) para expresar el comportamiento esperado en lenguaje casi natural. Herramientas: Cucumber, SpecFlow, Behave.
Feature: Retirada de dinero
Scenario: Retirada válida
Given una cuenta con saldo 1000
When retiro 200
Then el saldo es 800
Esto se convierte en requisito ejecutable que cualquier stakeholder puede leer y validar.
5. Frameworks de pruebas
No hay un estándar único; la filosofía es agnóstica de tecnología:
| Lenguaje | Frameworks populares |
|---|---|
| Java | JUnit, TestNG |
| C# | NUnit, MSTest, xUnit |
| Python | pytest, unittest |
| JavaScript/TS | Jest, Vitest, Mocha |
| E2E web | Cypress, Playwright, Selenium |
Actividad Grupal — Proyecto React con Cypress
- Stack: React + Vite + Cypress (pruebas E2E).
- El repositorio base está disponible en el foro y documentación.
- Los equipos pueden elegir el nivel de complejidad; se valora originalidad.
- Siguiente clase (taller): introducción a React + Git para la implementación.
Preguntas Tipo Examen
- Describe el ciclo Red-Green-Refactor del TDD.
- ¿Por qué se dice que TDD es fundamentalmente una técnica de diseño y no solo de testing?
- Explica el patrón Arrange/Act/Assert con un ejemplo sencillo.
- ¿Cuál es la diferencia entre TDD, ATDD y BDD?
- ¿Qué ventaja tiene que el tester sea una persona diferente al implementador?
- ¿Cómo contribuye el TDD a reducir el coste de detectar errores?