Saltar al contenido principal

🧪 Desarrollo Dirigido por Pruebas (TDD)

📖 Definición

TDD (Test-Driven Development) es una metodología de desarrollo donde escribes pruebas primero, luego escribes código para pasar esas pruebas. Sigue el ciclo Rojo-Verde-Refactor, mejorando la calidad del código, reduciendo errores y haciendo que la refactorización sea más segura. Las pruebas unitarias verifican funciones o componentes individuales de forma independiente.

🎯 Analogía Simple

Plano Primero

Desarrollo Tradicional
1. Construir casa
2. Verificar después de completar
3. Encontrar problemas → Grandes correcciones
4. Costo aumenta

TDD
1. Dibujar plano (Escribir prueba)
2. Construir según plano (Escribir código)
3. Verificar (Ejecutar prueba)
4. Mejorar (Refactorizar)
5. Seguro y preciso

⚙️ Cómo Funciona

Ciclo TDD (Rojo-Verde-Refactor)

🔴 Rojo (Falla)
└─ Escribir prueba → Falla (sin código)

🟢 Verde (Pasa)
└─ Escribir código mínimo → Prueba pasa

🔵 Refactor (Mejorar)
└─ Mejorar código → Prueba sigue pasando

Repetir → Mejora gradual

💡 Ejemplos Clave

Ejemplo Básico de TDD

// ========== 1. Rojo: Escribir prueba (falla) ==========
test('función add suma dos números', () => {
expect(add(2, 3)).toBe(5);
});
// FAIL - add no está definida

// ========== 2. Verde: Código mínimo (pasa) ==========
function add(a, b) {
return a + b;
}
// PASS ✅

// ========== 3. Refactor: Mejorar (si es necesario) ==========
// El código es simple, no se necesita mejora

Prueba Unitaria con Jest

// user.js
class User {
constructor(name, email) {
this.name = name;
this.email = email;
}

isValidEmail() {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(this.email);
}
}

// user.test.js
describe('User', () => {
let user;

beforeEach(() => {
user = new User('Juan', 'juan@example.com');
});

test('debe retornar true para email válido', () => {
expect(user.isValidEmail()).toBe(true);
});

test('debe retornar false para email inválido', () => {
user.email = 'invalid-email';
expect(user.isValidEmail()).toBe(false);
});
});

Prueba Asíncrona

test('función async retorna datos', async () => {
const data = await fetchData();
expect(data).toEqual({ name: 'John' });
});

Mocking

// Mock de función
const mockCallback = jest.fn(x => x * 2);

[1, 2, 3].forEach(mockCallback);

expect(mockCallback).toHaveBeenCalledTimes(3);

// Mock de módulo
jest.mock('axios');

test('fetchUser retorna datos de usuario', async () => {
axios.get.mockResolvedValue({ data: { id: 1 } });
const user = await fetchUser(1);
expect(user).toEqual({ id: 1 });
});

🤔 Preguntas Frecuentes

P1. ¿Beneficios de TDD?

R:

Pros:
1. Menos errores
2. Refactorización segura
3. Mejor calidad de código
4. Documentación
5. Confianza

Contras:
1. Inversión de tiempo inicial
2. Curva de aprendizaje
3. Mantenimiento de pruebas

Conclusión: Ganancia a largo plazo

P2. ¿Qué Probar?

R:

// ✅ Debe probar
1. Lógica de negocio
2. Casos extremos
3. Manejo de errores
4. APIs públicas

// ❌ No necesita probar
1. Bibliotecas externas
2. Getters/setters simples
3. Detalles de implementación privada

P3. ¿Objetivo de Cobertura?

R:

# Medir cobertura
npm test -- --coverage

# Objetivo:
80%+ cobertura // Objetivo realista
100% cobertura // Ideal pero poco práctico

# Recuerde:
Alta cobertura ≠ Buenas pruebas
¡Las pruebas significativas importan!

🎬 Resumen

TDD es la base de la calidad del software:

  • Rojo-Verde-Refactor: Ciclo central de TDD
  • Pruebas Unitarias: Rápidas y aisladas
  • Prueba Primero: Las pruebas guían el diseño
  • Mejora Continua: Red de seguridad para refactorización

¡Las pruebas son una inversión en tu yo futuro! 🧪✨