Yeda AI Tips · #096

English

Mantén tus tests DAMP, no DRY

Todo lo que sabes sobre DRY está mal — en los tests. En el código de la aplicación, la duplicación es deuda: dos copias de una misma regla van a divergir, y una de ellas va a estar mal. Pero los tests tienen otro trabajo. Un test es una especificación que tiene que explicarse sola a las 2 a.m. cuando falla. Los helpers sobre-compartidos te obligan a perseguir la lógica por cinco archivos para entender una sola falla. El equipo de testing de Google le puso nombre a la alternativa: mantén los tests DAMPDescriptive And Meaningful Phrases (frases descriptivas y con significado).

Por qué DRY sale mal en código de tests

El código de producción se lee por máquinas y se mantiene con abstracción. El código de tests lo lee un humano bajo presión, normalmente justo después de un build en rojo. Cada capa entre el nombre del test y la aserción — un bloque setUp tres pantallas más arriba, una fábrica makeUser() en otro archivo, un assertValidResponse() que verifica nueve cosas — es una página que el lector tiene que sostener en la cabeza.

El libro Software Engineering at Google lo dice claro: "un poco de duplicación está bien en los tests siempre que esa duplicación haga el test más simple y más claro". Los tests necesitan completitud (todo lo necesario para entender el test está en su cuerpo) y concisión (nada irrelevante lo está). El DRY estricto no optimiza ninguna de las dos.

Hay un segundo modo de falla: los helpers compartidos acumulan condicionales. Kent C. Dodds llama a la solución AHAAvoid Hasty Abstraction (evita la abstracción apresurada). Una utilidad de test que empezó con cinco líneas crece un objeto de opciones, luego un flag por cada llamador, hasta que leer el helper es más difícil que leer diez tests duplicados.

Reglas prácticas

SituaciónAplícale DRYDéjalo DAMP
Boilerplate de construcción de objetosHelper con defaults sobrescribibles
Los valores sobre los que el test hace asercionesInline, visibles en el cuerpo del test
Un paso nombrado en el escenario ("iniciar sesión como admin")Escríbelo o nómbralo descriptivamente
La plomería detrás de ese paso (llamadas HTTP, fixtures)Extráela
Aserción de un solo hecho conceptualUn helper de validación enfocado está bien
Helper genérico de "validar todo"NuncaDivídelo en asserts por hecho

El patrón detrás de la tabla es la división de Vladimir Khorikov: aplica DAMP a los qué (el escenario que un lector debe seguir) y DRY a los cómo (la mecánica por debajo). Los dos principios en realidad no chocan — DRY trata de no duplicar conocimiento del dominio, y dos tests que casualmente comparten cuatro líneas de setup no duplican conocimiento: son coincidentemente similares.

Cómo se ve un test DAMP

def test_expired_coupon_is_rejected():
    coupon = make_coupon(expires="2025-01-01")   # helper hides plumbing...
    cart = Cart(items=[book(price=30)])

    result = cart.apply(coupon, today="2026-07-22")  # ...values stay visible

    assert result.rejected
    assert result.reason == "coupon expired"

El helper construye el objeto; los valores con significado — la fecha de expiración, la fecha de hoy, la razón del rechazo — viven en el test. Cuando esto falla, el diagnóstico está en una sola pantalla. Sin safari de helpers.

Trucos avanzados

Recursos

Read this article in English

¿Construyendo una funcionalidad con IA? Yeda AI diseña, audita y entrega sistemas LLM de producción.

Habla con nosotros · Lee el blog