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 consecuencia | Efecto concreto |
|---|---|
| Bug en producción | El programa falla con la primera entrada real vacía. |
| Crash | División por cero o acceso fuera de límites. |
| Nota baja | Los 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¶
Valores máximos:
INT_MAX,LONG_MAX,SIZE_MAXpueden desbordar en sumas; probar con ellos.Cadenas: probar vacía, de un carácter y sin byte nulo (si el contrato lo permite).
Arreglos dinámicos: probar con
capacidad == 0si el TAD lo permite.Punto flotante: probar
0.0, negativos y valores muy cercanos.
Cómo detectarla¶
| Herramienta | Comando | Señal |
|---|---|---|
assert | gcc -DNDEBUG vs. sin -DNDEBUG | Pruebas que fallan sólo con bordes. |
drake | fuzzing de límites | Entradas extremas descubiertas automáticamente. |
nostromo | suite .in/.out | Casos de prueba de la cátedra. |
Checklist de autocontrol¶
¿Probé la colección vacía?
¿Probé con un solo elemento?
¿Probé el valor máximo y los negativos?
¿El contrato documenta qué bordes no se admiten?
Reglas relacionadas¶
0x2016h: Escribí el contrato de la función antes de implementarla — contrato que fija el dominio.
0x7002h: Validá los datos en la frontera del programa — validación en la frontera.
0x8002h: Escribí al menos una prueba por cláusula del contrato — una prueba por cláusula del contrato.
0x6004h: No reutilices una variable para propósitos distintos — inicialización de los casos extremos.