Metodología TDD: red, green y refactor

Resumen

El Test Driven Development (TDD) invierte el orden tradicional del desarrollo: primero escribes los tests y después construyes el componente. Esta metodología te permite refactorizar con seguridad, reducir bugs y ahorrarte dolores de cabeza cuando tu software ya es robusto y los casos de uso están claros.

Cómo funciona el ciclo red, green y refactor en TDD

El corazón de TDD es un ciclo de tres fases que guía cada componente que escribes.

  • Red: escribes el test antes de que exista el componente. Como no hay código todavía, el test falla. Ese fallo es la señal de que vas por buen camino [00:30].
  • Green: creas el componente mínimo necesario para que el test pase. Aquí el objetivo no es que sea bonito, sino que funcione.
  • Refactor: limpias y mejoras el código con la red de seguridad que te dan los tests. Si rompes algo, el test te avisa de inmediato.

¿Cuándo conviene usar TDD? Cuando ya tienes un software robusto y conoces los casos de uso. Si estás en fase experimental, los casos de prueba cambiarán constantemente y la metodología pierde sentido [01:25].

Cómo escribir el primer test antes de crear el componente

Imagina que vas a construir un contador en React. Antes de tocar el componente, creas la carpeta Contador y dentro un archivo contador.test.tsx. Ese archivo es tu punto de entrada al rojo del ciclo [02:00].

Dentro del test importas describe, it y expect desde vitest, y render, screen y fireEvent desde testing library react. Defines una suite para el componente Contador y validas dos casos de uso muy concretos:

  1. Que al renderizarse muestre el valor inicial en cero.
  2. Que al hacer clic en un botón llamado Incrementar, el contador suba a uno.

Cómo se ve un caso de prueba real

En el primer test renderizas el componente (que aún no existe), buscas el texto Contador: 0 con screen.getByText y haces la aserción con el matcher toBeInTheDocument.

En el segundo test simulas el clic. Usas fireEvent.click dentro de un act asíncrono sobre el botón Incrementar y verificas que ahora aparezca Contador: 1 en pantalla [04:10].

En este punto los tests están rotos, y eso está bien. Es la fase red funcionando como debe.

Cómo construir el componente para pasar a la fase verde

Ahora sí creas contador.tsx. Defines un estado con useState inicializado en cero, retornas un div con el texto Contador: seguido del valor del estado, y agregas un botón con el texto Incrementar [05:30].

tsx import { useState } from 'react';

export const Contador = () => { const [contador, setContador] = useState(0);

return ( <div> <p>Contador: {contador}</p> <button onClick={() => setContador(contador + 1)}> Incrementar </button> </div> ); };

Un detalle importante: el texto en el componente debe coincidir exactamente con el que pones en el test. Si tu test busca Contador: con dos puntos, tu JSX debe escribirlo igual. De lo contrario, getByText no lo encuentra.

Guardas, importas el componente en el archivo de test y los tests pasan. Llegaste al green.

¿Por qué el test falla si el texto no coincide exactamente? Porque getByText hace una comparación literal del contenido. Un espacio o un signo de puntuación distinto rompe la búsqueda.

Por qué el refactor es la fase más poderosa de TDD

Aquí viene lo interesante. Tienes el componente funcionando, pero no te gusta dejar la actualización de estado directamente en el onClick. Decides extraerla a una función llamada handleIncrementar [07:00].

tsx const handleIncrementar = () => { setContador(contador + 1); };

<button onClick={handleIncrementar}>Incrementar</button>

Guardas y los tests siguen pasando. Esa es la magia: puedes mejorar la estructura del código sin miedo a romper la funcionalidad, porque los tests actúan como un guardián. Si llegaras a hacer un refactor incorrecto, el test te lo grita al instante.

¿Qué protege exactamente TDD durante un refactor? Protege el comportamiento esperado del componente. Si cambias la implementación pero mantienes el mismo resultado visible, los tests pasan. Si rompes el comportamiento, fallan.

Reto para practicar TDD con un componente nuevo

Al lado del contador, crea otro componente aplicando la misma metodología. Algunas ideas:

  • Una to-do list donde al agregar elementos aparezcan en una lista.
  • Un temporizador que muestre el tiempo al iniciar y la palabra pausa al pausar.
  • Cualquier componente con casos de uso claros que puedas describir antes de escribir el código.

La clave está en empezar por el test. Define qué debe hacer el componente, escribe los casos de prueba, mira cómo fallan, construye lo mínimo para que pasen y refactoriza con tranquilidad. Comparte lo que hagas en la sección de aportes.