Compartir en Twitter
Go to Homepage

GUÍA COMPLETA DE TEST-DRIVEN DEVELOPMENT EN JAVASCRIPT Y REACT

October 8, 2025

Introducción al Test-Driven Development

El desarrollo basado en pruebas, conocido como Test-Driven Development (TDD), es una práctica de programación que prioriza la creación de pruebas antes de escribir el código de la aplicación. Este enfoque fomenta la construcción de software confiable y mantenible al definir claramente los resultados esperados desde el inicio. En este tutorial, exploraremos cómo implementar TDD en aplicaciones JavaScript y React, utilizando herramientas como Jest y React Testing Library. Cubriremos desde los conceptos básicos hasta ejemplos prácticos, incluyendo pruebas unitarias, de integración y de extremo a extremo, junto con el uso de dobles de prueba.

¿Qué es el Test-Driven Development?

El Test-Driven Development es una metodología donde se escriben pruebas que especifican el comportamiento esperado de un programa antes de desarrollar su lógica. Este proceso asegura que el código cumpla con los requisitos establecidos desde el principio. El flujo de trabajo típico de TDD sigue estos pasos:

  1. Escribir una prueba que defina el resultado esperado.
  2. Ejecutar la prueba, que inicialmente fallará porque el código aún no existe.
  3. Desarrollar el código mínimo necesario para pasar la prueba.
  4. Ejecutar nuevamente la prueba para verificar que pasa.
  5. Refactorizar el código si es necesario, asegurando que las pruebas sigan pasando.
  6. Repetir el ciclo hasta completar la funcionalidad.

Por ejemplo, si deseas crear una calculadora de suma, primero escribirías una prueba que especifique que sumar 4 y 6 debe devolver 10. Luego, desarrollarías la función que realiza esta operación.

// Prueba
function additionCalculatorTester() {
    if (additionCalculator(4, 6) === 10) {
        console.log("✔ Prueba Exitosa");
    } else {
        console.error("❌ Prueba Fallida");
    }
}

// Programa
function additionCalculator(a, b) {
    return a + b;
}

// Ejecutar la prueba
additionCalculatorTester();

Ejemplo de Flujo de Trabajo TDD en JavaScript

A continuación, se detalla un ejemplo práctico de TDD en JavaScript para una calculadora de suma, siguiendo los pasos del flujo de trabajo.

Escribir la Prueba

Primero, se crea una prueba que especifica el comportamiento esperado. En este caso, se espera que la función additionCalculator sume dos números correctamente.

function additionCalculatorTester() {
    if (additionCalculator(4, 6) === 10) {
        console.log("✔ Prueba Exitosa");
    } else {
        console.error("❌ Prueba Fallida");
    }
}

Desarrollar el Programa

Se escribe el código necesario para pasar la prueba, implementando la función additionCalculator.

function additionCalculator(a, b) {
    return a + b;
}

Ejecutar la Prueba

Se ejecuta la prueba para verificar si el programa cumple con las expectativas.

additionCalculatorTester();

Refactorizar la Prueba

Si es necesario, se refactoriza la prueba para mejorar su legibilidad, por ejemplo, utilizando un operador condicional.

function additionCalculatorTester() {
    additionCalculator(4, 6) === 10
        ? console.log("✔ Prueba Exitosa")
        : console.error("❌ Prueba Fallida");
}

Refactorizar el Programa

El programa también puede refactorizarse, por ejemplo, convirtiendo la función en una función flecha.

const additionCalculator = (a, b) => a + b;

Reejecutar la Prueba

Se vuelve a ejecutar la prueba para confirmar que el programa sigue funcionando correctamente.

additionCalculatorTester();

Este ejemplo ilustra cómo TDD permite desarrollar código de manera incremental, asegurando que cada cambio mantenga la funcionalidad esperada.

Cómo Usar Jest para Implementar Pruebas

Jest es una herramienta de pruebas ampliamente utilizada que simplifica la implementación de TDD en JavaScript. A continuación, se explica cómo configurar y usar Jest para probar una calculadora de suma.

Configuración Inicial

  1. Verificar Node y NPM: Asegúrate de tener Node.js (versión 10.16 o superior) y NPM (versión 5.6 o superior) instalados. Puedes descargarlos desde el sitio oficial de Node.js.

  2. Crear un Directorio de Proyecto:

mkdir calculadora-suma-jest
cd calculadora-suma-jest
  1. Inicializar package.json:
npm init -y
  1. Instalar Jest:
npm install jest --save-dev
  1. Configurar Jest en package.json:
{
    "scripts": {
        "test": "jest"
    }
}
  1. Crear Archivos del Proyecto:
touch additionCalculator.js
touch additionCalculator.test.js

Escribir la Prueba

En el archivo additionCalculator.test.js, se escribe una prueba que especifica el comportamiento esperado.

const additionCalculator = require("./additionCalculator");

test("suma de 4 y 6 igual a 10", () => {
    expect(additionCalculator(4, 6)).toBe(10);
});

En este código, test define el caso de prueba, expect verifica el resultado y toBe compara con un valor primitivo.

Desarrollar el Programa

En additionCalculator.js, se implementa la función para pasar la prueba.

function additionCalculator(a, b) {
    return a + b;
}

module.exports = additionCalculator;

Ejecutar la Prueba

Se ejecuta la prueba con:

npm run test

Jest mostrará un mensaje indicando si la prueba pasó o falló.

Refactorizar la Prueba

Para probar más casos, como sumar múltiples números o manejar casos sin argumentos, se refactoriza la prueba.

const additionCalculator = require("./additionCalculator");

describe("Casos de prueba de additionCalculator", () => {
    test("suma de 4 y 6 igual a 10", () => {
        expect(additionCalculator(4, 6)).toBe(10);
    });

    test("suma de 100, 50, 20, 45 y 30 igual a 245", () => {
        expect(additionCalculator(100, 50, 20, 45, 30)).toBe(245);
    });

    test("suma de 7 igual a 7", () => {
        expect(additionCalculator(7)).toBe(7);
    });

    test("sin argumentos devuelve 0", () => {
        expect(additionCalculator()).toBe(0);
    });
});

La función describe agrupa casos de prueba relacionados, mejorando la organización.

Refactorizar el Programa

Se ajusta additionCalculator para manejar múltiples argumentos usando el operador rest y reduce.

function additionCalculator(...numbers) {
    return numbers.reduce((sum, item) => sum + item, 0);
}

module.exports = additionCalculator;

Reejecutar la Prueba

Se vuelve a ejecutar la prueba para verificar que todo funciona correctamente.

npm run test

Para automatizar las pruebas, agrega --watchAll al script de prueba en package.json:

{
    "scripts": {
        "test": "jest --watchAll"
    }
}

Uso de Módulos ES6 con Jest

Jest no soporta módulos ES6 de forma nativa, pero puedes habilitarlos con Babel. Sigue estos pasos:

  1. Instalar Babel:
npm install @babel/preset-env --save-dev
  1. Crear .babelrc:
touch .babelrc
  1. Configurar .babelrc:
{ "presets": ["@babel/preset-env"] }
  1. Ajustar Archivos:

Cambia require por import en additionCalculator.test.js:

import additionCalculator from "./additionCalculator";

test("suma de 4 y 6 igual a 10", () => {
    expect(additionCalculator(4, 6)).toBe(10);
});

Y en additionCalculator.js:

export default function additionCalculator(...numbers) {
    return numbers.reduce((sum, item) => sum + item, 0);
}
  1. Reejecutar la Prueba:
npm run test

Esto permite usar la sintaxis moderna de ES6 en proyectos con Jest.

Ventajas del Test-Driven Development

El TDD ofrece múltiples beneficios que mejoran el proceso de desarrollo de software.

Claridad en el Propósito del Programa

TDD te obliga a definir claramente el comportamiento esperado antes de escribir el código, lo que ayuda a comprender mejor los requisitos del programa. Al escribir pruebas primero, documentas las expectativas, lo que facilita el desarrollo enfocado.

Mayor Confianza en el Código

Las pruebas proporcionan una red de seguridad, asegurando que el código funcione como se espera, incluso después de refactorizaciones o actualizaciones. Esto aumenta la confianza en la estabilidad del programa.

Tipos de Pruebas en TDD

TDD abarca diferentes tipos de pruebas, cada una con un propósito específico.

Pruebas Unitarias

Las pruebas unitarias evalúan unidades independientes de código, como una función que no depende de otras partes del sistema. Por ejemplo, la prueba inicial de additionCalculator es una prueba unitaria porque verifica una función aislada.

test("suma de 4 y 6 igual a 10", () => {
    expect(additionCalculator(4, 6)).toBe(10);
});

Pruebas de Integración

Las pruebas de integración verifican el funcionamiento de componentes que dependen de otros, como una función que usa métodos externos. La versión refactorizada de additionCalculator que usa reduce es un ejemplo, ya que depende de una API de JavaScript.

test("suma de múltiples números", () => {
    expect(additionCalculator(100, 50, 20)).toBe(170);
});

Pruebas de Extremo a Extremo

Las pruebas de extremo a extremo (E2E) evalúan la interfaz de usuario completa, simulando la interacción del usuario con la aplicación. Estas pruebas verifican que todos los componentes trabajen juntos correctamente.

Dobles de Prueba

Los dobles de prueba son objetos que imitan dependencias externas, como bases de datos o APIs. Incluyen:

  • Dummy: Imita valores de parámetros para pruebas.
  • Mock: Simula una dependencia sin considerar sus respuestas.
  • Stub: Devuelve valores predefinidos para probar diferentes escenarios.
  • Fake: Implementa una versión simplificada de una dependencia, como una base de datos local.

Por ejemplo, un stub podría simular una respuesta de API:

const mockApiResponse = () => ({ data: "respuesta simulada" });

Cómo Probar Componentes de React

Probar componentes de React requiere un test runner (como Jest) y una biblioteca de pruebas de componentes (como React Testing Library). A continuación, se detalla un proyecto práctico.

Configuración del Proyecto

  1. Verificar Node y NPM: Usa Node 10.16+ y NPM 5.6+.

  2. Crear un Proyecto React:

npx create-react-app react-testing-project
cd react-testing-project
  1. Limpiar la Carpeta src:

Elimina todos los archivos en src y crea:

touch src/index.js
touch src/App.js
touch src/App.test.js
  1. Configurar index.js:
import React from "react";
import { createRoot } from "react-dom/client";
import App from "./App";

createRoot(document.getElementById("root")).render(<App />);

Escribir la Prueba

En App.test.js, se especifica que el componente App debe renderizar un encabezado con el texto “CodeSweetly Test”.

import React from "react";
import { render, screen } from "@testing-library/react";
import "@testing-library/jest-dom";
import App from "./App";

test("encabezado codesweetly test", () => {
    render(<App />);
    expect(screen.getByRole("heading")).toHaveTextContent(/codesweetly test/i);
});

Desarrollar el Componente

En App.js, se crea el componente para pasar la prueba.

import React from "react";

const App = () => <h1>CodeSweetly Test</h1>;

export default App;

Ejecutar la Prueba

npm test App.test.js

Refactorizar la Prueba

Para probar una interacción, como cambiar el texto del encabezado al hacer clic en un botón, se refactoriza App.test.js.

import React from "react";
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import "@testing-library/jest-dom";
import App from "./App";

describe("Componente App", () => {
    test("encabezado codesweetly test", () => {
        render(<App />);
        expect(screen.getByRole("heading")).toHaveTextContent(
            /codesweetly test/i
        );
    });

    test("actualización de encabezado", () => {
        render(<App />);
        const button = screen.getByRole("button", {
            name: "Actualizar Encabezado",
        });
        userEvent.click(button);
        expect(screen.getByRole("heading")).toHaveTextContent(
            /proyecto codesweetly/i
        );
    });
});

Refactorizar el Componente

Se ajusta App.js para manejar el cambio de estado.

import React, { useState } from "react";

const App = () => {
    const [heading, setHeading] = useState("CodeSweetly Test");

    const handleClick = () => {
        setHeading("Proyecto CodeSweetly");
    };

    return (
        <>
            <h1>{heading}</h1>
            <button type="button" onClick={handleClick}>
                Actualizar Encabezado
            </button>
        </>
    );
};

export default App;

Reejecutar la Prueba

npm test App.test.js

Iniciar la Aplicación

npm start

Esto abrirá la aplicación en el navegador, mostrando los cambios.

Conclusiones

El Test-Driven Development es una práctica poderosa que mejora la calidad y mantenibilidad del código en aplicaciones JavaScript y React. Al escribir pruebas antes del código, los desarrolladores definen claramente los requisitos, lo que resulta en un software más robusto y confiable. Herramientas como Jest y React Testing Library facilitan la implementación de TDD, permitiendo pruebas unitarias, de integración y de extremo a extremo. Incorporar TDD en tu flujo de trabajo no solo aumenta la confianza en el código, sino que también optimiza el proceso de desarrollo, reduciendo errores y mejorando la escalabilidad de los proyectos.