A4.B Errores y casos límite¶
El código casi nunca falla con los datos «normales»: falla en los bordes (el primero, el último, el cero, el vacío) y con los datos inválidos. Esas son las pruebas que más valen.
Probar que algo falla¶
También hay que comprobar que el código rechaza lo incorrecto, con el error y el mensaje adecuados.
assertThrows(IllegalArgumentException.class, () -> ...) comprueba que el código lanza esa excepción y la devuelve, para poder mirar su mensaje con getMessage(). Está en JUnit 4 desde la versión 4.13; antes se usaba @Test(expected = ...), que no deja mirar el mensaje.
Casos límite¶
Un caso límite es un valor en la frontera entre dos comportamientos. Si un descuento va de 0 a 100, prueba 0 y 100 (los extremos válidos) y -1 y 101 (justo fuera). Los errores de «uno de más o de menos» (< en vez de <=) viven ahí.
| Qué pruebas | Valores típicos |
|---|---|
| Números con un rango | El mínimo, el máximo, justo debajo y justo encima |
| Colecciones y texto | Vacío, un solo elemento, muchos |
| Búsquedas | El primero, el último, uno que no está |
| Divisiones y porcentajes | Cero, uno, el límite |
Varios casos con una tabla¶
Cuando la comprobación es la misma y solo cambian los datos, se escribe una prueba que recorre una tabla de casos (entrada y resultado esperado):
Un Map y un bucle dentro de una prueba; el primer parámetro de assertEquals es el mensaje que dice qué caso falló.
El ejemplo¶
Las pruebas del carrito: dos para los errores, una con la tabla de descuentos y otra para el porcentaje fuera de rango.
CarritoCasosTest.java
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThrows;
import java.util.Map;
import java.util.TreeMap;
import org.junit.Before;
import org.junit.Test;
public class CarritoCasosTest {
private Carrito carrito;
@Before
public void preparar() {
carrito = new Carrito();
}
@Test
public void unaCantidadCeroONegativaLanzaUnErrorConUnMensajeClaro() {
// assertThrows (JUnit 4.13) comprueba que se lanza la excepción y la devuelve para mirar su mensaje
IllegalArgumentException error = assertThrows(IllegalArgumentException.class, () -> carrito.agregar("tarta", 1800, 0));
assertEquals("la cantidad debe ser mayor que cero", error.getMessage());
assertThrows(IllegalArgumentException.class, () -> carrito.agregar("tarta", 1800, -1));
}
@Test
public void unPrecioNegativoLanzaUnError() {
assertThrows(IllegalArgumentException.class, () -> carrito.agregar("tarta", -5, 1));
}
@Test
public void descuentosDe0_10_50Y100PorCientoCasosLimiteIncluidos() {
carrito.agregar("tarta", 1800, 2);
carrito.agregar("galleta", 100, 12);
Map<Integer, Integer> casos = new TreeMap<>(Map.of(0, 4800, 10, 4320, 50, 2400, 100, 0)); // porcentaje -> total esperado
for (Map.Entry<Integer, Integer> caso : casos.entrySet()) {
// el primer argumento es el mensaje que se verá si esta comprobación falla
assertEquals("con " + caso.getKey() + " %", (int) caso.getValue(), carrito.conDescuento(caso.getKey()));
}
}
@Test
public void unPorcentajeFueraDe0A100LanzaUnError() {
assertThrows(IllegalArgumentException.class, () -> carrito.conDescuento(101));
assertThrows(IllegalArgumentException.class, () -> carrito.conDescuento(-1));
}
}
Al ejecutar las pruebas:
....
OK (4 tests)
Los descuentos esperados se escribieron a mano (4800 → 4320 con un 10 %): si copiaras la fórmula del código en la prueba, repetirías también sus errores.
Cobertura no es calidad
Un programa de pruebas puede ejecutar todas las líneas del código y aun así no comprobar casi nada. Mide cuántos casos importantes tienes cubiertos (bordes, errores, datos raros), no solo cuántas líneas pasan por las pruebas.
Errores frecuentes¶
| Error | Cómo evitarlo |
|---|---|
| Probar solo el caso feliz | Añade siempre al menos un borde y un error |
| Comprobar que «lanza algún error» sin mirar cuál | Comprueba el tipo y, si importa, el mensaje |
| Un bucle de casos donde el primer fallo oculta a los demás | Usa el mecanismo del marco para indicar el caso (reason, subTest...) |
| Escribir las pruebas copiando la implementación | Calcula el resultado esperado a mano o con otra vía |
Para practicar¶
Los ejercicios A4.2, A4.3 y A4.5 piden pruebas de casos normales, de errores y de límites con una tabla. Para ver la misma idea en los otros lenguajes: Pasar de uno a otro.