Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Regla 0x8002h: Escribí al menos una prueba por cláusula del contrato

Verificacion, testing y depuracion (0x80XX)

Universidad Nacional de Río Negro

0x8002h: Escribí al menos una prueba por cláusula del contrato

Enunciado normativo

Cada cláusula del contrato de una función (cada precondición, cada postcondición y cada caso de error documentado) DEBE tener al menos una prueba que la verifique. NO DEBE considerarse terminada una función sin pruebas que cubran su especificación completa.

¿Por qué existe esta regla?

El problema

Una prueba que sólo verifica “el caso feliz” no demuestra que la función cumpla su contrato: deja sin cubrir justamente las cláusulas que describen errores y bordes. Como el contrato enumera explícitamente lo que la función promete, cada promesa es un candidato directo a prueba. Esto convierte el testing en una tarea mecánica y completa, no en una inspiración.

Además, las pruebas sirven de documentación ejecutable: muestran a un lector futuro cómo se usa la función y qué se espera ante cada entrada.

Consecuencias de violarla

Tipo de consecuenciaEfecto concreto
Errores no detectadosEl camino de error nunca se ejecuta hasta producción.
RegresionesUn cambio rompe una cláusula sin que nadie lo note.
Falsa coberturaMuchas pruebas del mismo caso y ninguna del borde.
DiseñoUn contrato que no se puede probar suele estar mal especificado.

Fundamento en la cátedra

Extiende 0x8001h: Una aserción por cada función de prueba (una aserción por prueba) del “cómo” al “qué”: no basta con escribir asserts, hay que asegurarse de cubrir cada cláusula del contrato. Se apoya en 0x2016h: Escribí el contrato de la función antes de implementarla (contrato) y 0x7006h: Probá explícitamente los casos borde (casos borde).

Alcance y excepciones

Aplica a funciones con contrato explícito. Las funciones triviales (getters) pueden cubrirse con una prueba general. La obligación es proporcional a la cantidad de cláusulas: a más promesas, más pruebas.

Ejemplos exhaustivos

❌ Contraejemplo 1 — Sólo el caso feliz

Contrato: promedio(v, n) devuelve el promedio, y 0.0 si n == 0.

assert(promedio((int[]){2, 4, 6}, 3) == 4.0);
/* fin de las pruebas */

Por qué falla: la cláusula “si n == 0 devuelve 0.0” no se prueba; podría estar mal implementada y nadie lo sabría.

❌ Contraejemplo 2 — Muchas pruebas redundantes

assert(promedio((int[]){1, 2}, 2) == 1.5);
assert(promedio((int[]){2, 4}, 2) == 3.0);
assert(promedio((int[]){3, 6}, 2) == 4.5);

Por qué falla: tres variantes del mismo caso (dos elementos). Cubren lo mismo y dejan sin probar el borde.

✅ Ejemplo conforme 1 — Una prueba por cláusula

/* Clausula: caso comun. */
assert(promedio((int[]){2, 4, 6}, 3) == 4.0);

/* Clausula: arreglo vacio devuelve 0.0. */
assert(promedio(NULL, 0) == 0.0);

/* Clausula: un elemento. */
assert(promedio((int[]){7}, 1) == 7.0);

Cada assert corresponde a una promesa distinta del contrato.

✅ Ejemplo conforme 2 — Cobertura de errores

Contrato: pila_apilar devuelve PILA_LLENA si no hay capacidad.

pila_t *p = pila_crear(1);
assert(pila_apilar(p, 10) == PILA_OK);
assert(pila_apilar(p, 20) == PILA_LLENA);
pila_destruir(p);

El caso de error también es una cláusula del contrato y se prueba.

⚠️ Casos límite

Cómo detectarla

HerramientaComandoSeñal
assertgcc archivo.c -o test && ./testCada cláusula tiene su assert.
gcovgcc --coverage + gcovLíneas de la función no ejecutadas por las pruebas.
dreddreporte de coberturaCláusulas del contrato sin prueba.

Checklist de autocontrol

Reglas relacionadas