Skip to main content

Inicia sesión en CleanKata

Sigue tu progreso, gana XP y desbloquea todas las lecciones.

Al iniciar sesión aceptas nuestros Términos de uso y Política de privacidad.

Código Limpio60 XP6 min

Pruebas Unitarias Limpias

Las pruebas son código de primera clase — las pruebas sucias son tan costosas de mantener como el código de producción.

Las Tres Leyes del TDD

1. No escribas código de producción hasta tener un test que falle. 2. No escribas más test del necesario para fallar. 3. No escribas más código de producción del necesario para pasar el test. El ciclo es: Rojo → Verde → Refactorizar. Los tests escritos después del código son a menudo incompletos: testean lo que escribiste, no lo que el código debería hacer.

// TDD cycle for a discount calculator

// ── Red ─────────────────────────────────────────
function test_no_discount_for_regular_users():
    calc = new DiscountCalculator()
    assert calc.apply(100.0, "regular") == 100.0  // fails — class doesn't exist

// ── Green ───────────────────────────────────────
class DiscountCalculator:
    function apply(price, tier):
        return price  // simplest code to pass

// ── Refactor ────────────────────────────────────
// Next test drives the next behavior:
function test_10_percent_off_for_premium_users():
    calc = new DiscountCalculator()
    assert calc.apply(100.0, "premium") == 90.0

La Regla F.I.R.S.T.

Los tests limpios son Rápidos (milisegundos — sin BD, sin red), Independientes (ningún test prepara estado para otro), Repetibles (mismo resultado en cualquier entorno), de Validación automática (pasan o fallan — sin lectura humana), Puntuales (escritos justo antes del código de producción). Un conjunto de tests lento y dependiente del orden es uno que los desarrolladores dejan de ejecutar.

No cumple FIRST — lento, con orden dependiente y BD real

class TestUserService:
    function test_create_user():
        db = RealDatabase.connect("localhost:5432")  // slow!
        service = new UserService(db)
        user = service.create("Alice", "a@t.com")
        savedUserId = user.id  // ← shared state!

    function test_find_user():
        user = service.find(savedUserId)
        assert user.name == "Alice"  // depends on prev test

FIRST — rápido, aislado, usa un fake

class TestUserService:
    function setup():
        db = new FakeDatabase()   // fast, in-memory
        service = new UserService(db)

    function test_create_returns_user_with_given_name():
        user = service.create("Alice", "a@t.com")
        assert user.name == "Alice"

    function test_find_returns_null_for_unknown_id():
        result = service.find("unknown-id")
        assert result == null

Una Aserción por Test

Cada función de test debe verificar un concepto. Múltiples aserciones por test significan múltiples modos de fallo: cuando falla, no sabes qué concepto se rompió. Usa nombres de test descriptivos como documentación: test_inactive_users_cannot_place_orders indica la regla que se está testando. Los futuros desarrolladores leerán los tests para entender el comportamiento, no el código fuente.

Un test, seis aserciones, seis puntos de fallo

function test_user():
    user = new User("alice", "alice@test.com")
    assert user.name == "alice"
    assert user.email == "alice@test.com"
    assert user.isActive == true
    user.deactivate()
    assert user.isActive == false
    user.setRole("admin")
    assert user.role == "admin"

Un concepto por test

function test_user_is_active_by_default():
    user = new User("alice", "alice@test.com")
    assert user.isActive == true

function test_user_becomes_inactive_after_deactivation():
    user = new User("alice", "alice@test.com")
    user.deactivate()
    assert user.isActive == false

function test_user_role_can_be_set():
    user = new User("alice", "alice@test.com")
    user.setRole("admin")
    assert user.role == "admin"

Desafío de Código

Divide el Test Dios — este test tiene 5 conceptos diferentes. Separa cada uno en su propia función con un nombre descriptivo que se lea como una regla.

💡Conclusión clave

Los tests son el primer cliente de tu código. Tests limpios, rápidos y enfocados hacen posible el refactoring sin miedo.

🔧 Algunos ejercicios pueden tener errores. Si algo parece incorrecto, usa el botón Feedback (abajo a la derecha) para reportarlo — nos ayuda a corregirlo rápido.

Pista: Lee cada assertion y pregunta: ¿qué regla individual verifica esto? Dale un nombre como 'deberia_rechazar_email_vacio'. Una assertion → una regla → una función cuyo nombre documenta el comportamiento.

✗ Tu versión

Pruebas Unitarias Limpias — CleanKata — CleanKata