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 0x7006h: Probá explícitamente los casos borde

Robustez y manejo de errores (0x70XX)

Universidad Nacional de Río Negro

0x7006h: Probá explícitamente los casos borde

Enunciado normativo

Para cada función DEBEN probarse, como mínimo, los casos borde: colección vacía, colección de un elemento, valor máximo o límite del dominio, valor cero o negativo cuando aplique. NO DEBE validarse sólo con un caso “típico” del medio.

¿Por qué existe esta regla?

El problema

Los errores se esconden en los extremos. Un algoritmo que funciona con “cinco elementos” puede fallar con cero (división por cero, acceso a v[0]) o con uno (el lazo no entra, el máximo queda indefinido). Los ejemplos del enunciado suelen ser del medio y no exponen estos bordes.

Probar explícitamente los extremos es la forma más eficaz de descubrir errores de inicialización, de índices y de condiciones de corte antes de entregar.

Consecuencias de violarla

Tipo de consecuenciaEfecto concreto
Bug en producciónEl programa falla con la primera entrada real vacía.
CrashDivisión por cero o acceso fuera de límites.
Nota bajaLos jueces de la cátedra usan casos borde por diseño.
Falsa confianza“Funciona” sólo con el ejemplo de prueba.

Fundamento en la cátedra

Es la aplicación práctica de los contratos (0x2016h: Escribí el contrato de la función antes de implementarla) y de la verificación (0x8002h: Escribí al menos una prueba por cláusula del contrato). Los conjuntos de prueba de la materia incluyen siempre casos vacíos, de un elemento y extremos.

Alcance y excepciones

Aplica a toda función con dominio numérico, arreglos, cadenas o punteros. Una función cuyo contrato excluye explícitamente el caso vacío (precondición n >= 1) no necesita manejarlo, pero el borde debe estar documentado y probado por el llamador.

Ejemplos exhaustivos

❌ Contraejemplo 1 — Sólo el caso del medio

int maximo(const int v[], size_t n)
{
    int m = v[0];
    for (size_t i = 1; i < n; i++) {
        if (v[i] > m) {
            m = v[i];
        }
    }
    return m;
}

Si sólo se prueba con {3, 7, 1}, funciona. Con n == 0 lee v[0] fuera de límites; con n == 1 devuelve correctamente sólo por casualidad.

❌ Contraejemplo 2 — Cadena sin el caso vacío

size_t longitud(const char *s)
{
    size_t n = 0;
    while (s[n] != '\0') {
        n++;
    }
    return n;
}

Con s = "" funciona, pero si el contrato permite s == NULL, s[0] desreferencia nulo. El caso NULL/vacío debe decidirse y probarse.

✅ Ejemplo conforme 1 — Conjunto de pruebas por borde

assert(maximo((int[]){5}, 1) == 5);          /* un elemento   */
assert(maximo((int[]){2, 9, 4}, 3) == 9);    /* caso comun    */
assert(maximo((int[]){-3, -1, -7}, 3) == -1);/* negativos     */
assert(maximo((int[]){INT_MAX}, 1) == INT_MAX);/* limite       */

Cada assert cubre un borde; el caso vacío se maneja con una precondición explícita o se devuelve un error.

✅ Ejemplo conforme 2 — Decisión de contrato para el vacío

/**
 * @pre n >= 1 y v != NULL.
 */
int maximo(const int v[], size_t n);

Con el contrato claro, el llamador valida n >= 1 antes de llamar y prueba ese borde (0x7002h: Validá los datos en la frontera del programa).

⚠️ Casos límite

Cómo detectarla

HerramientaComandoSeñal
assertgcc -DNDEBUG vs. sin -DNDEBUGPruebas que fallan sólo con bordes.
drakefuzzing de límitesEntradas extremas descubiertas automáticamente.
nostromosuite .in/.outCasos de prueba de la cátedra.

Checklist de autocontrol

Reglas relacionadas