Probar lo que falla
Cómo se prueba código que depende de tres almacenes del sistema: la frontera que hay que dibujar, los dobles que valen la pena, y la matriz de escenarios que de verdad rompen.
La frontera
Una interfaz pequeña, y todo lo demás se prueba contra ella:
pub trait Almacen: Send + Sync { fn leer(&self, cuenta: &str) -> Result<Option<String>, ErrorAlmacen>; fn guardar(&self, cuenta: &str, secreto: &str) -> Result<(), ErrorAlmacen>; fn borrar(&self, cuenta: &str) -> Result<(), ErrorAlmacen>; fn disponible(&self) -> bool;}// y el error enumera las causas del nivel 38.1, no las de cada plataformapub enum ErrorAlmacen { NoExiste, Denegado, NoDescifra, SinServicio, DemasiadoGrande, Otro(String) }El enumerado es la pieza clave. Con él, la lógica de sesión —que es donde está todo lo interesante del nivel 38.4— se prueba entera sin tocar ningún almacén real: solo hace falta un doble que devuelva la causa que quieras.
El doble
Suficiente con esto:
struct AlmacenFalso { datos: Mutex<HashMap<String, String>>, fallo: Mutex<Option<ErrorAlmacen>>, // lo que devolverá la próxima llamada}impl AlmacenFalso { fn provocar(&self, e: ErrorAlmacen) { *self.fallo.lock().unwrap() = Some(e); }}Con un mapa en memoria y una causa de fallo programable se cubren todos los escenarios del nivel 38.4 sin salir de una prueba unitaria: el refresco rotado, la carrera de dos refrescos, el cierre sin conexión, el testigo que no descifra.
Y el doble hace visible una cosa que el almacén real esconde: cuántas veces llama tu código al almacén. Si una prueba de una operación normal muestra seis lecturas, tienes el problema del nivel 35.2 —seis oportunidades de diálogo— y lo has descubierto sin necesidad de macOS.
La matriz
La lectura de la tabla: casi todo se automatiza salvo el escenario que provoca el fallo. La reacción de tu código a cada causa se prueba con el doble; que la causa ocurra de verdad se comprueba una vez, a mano, por plataforma.
Las tres pruebas manuales que hay que hacer sí o sí
Una por sistema, y son las del nivel 35.5, 36.4 y 37.4:
- macOS: cambiar el identificador del paquete, provocar el diálogo, denegar, y comprobar que no hay bucle.
- Windows: restablecer la contraseña de un usuario de prueba desde una cuenta de administrador y comprobar que el secreto muerto se borra.
- Linux: arrancar sin almacén y comprobar que la aplicación funciona diciendo que no puede recordar la sesión.
Tres pruebas, media hora cada una, una sola vez —o cada vez que se toque esta capa—. Es la mejor relación entre tiempo invertido e incidencias evitadas de toda la fase.