unit testing - software - ¿Cómo escribo una prueba de unidad de óxido que asegura que ha ocurrido un ataque de pánico?
pruebas unitarias laravel (4)
Tengo una función Rust que panic
bajo alguna condición y deseo escribir un caso de prueba para validar si la función está en pánico o no. ¡No pude encontrar nada excepto la assert!
y assert_eq!
macros. ¿Hay algún mecanismo para probar esto?
Podría generar una nueva tarea y verificar si esa tarea entra en pánico o no. ¿Tiene sentido?
Devolver un Result<T, E>
no es adecuado en mi caso.
Deseo agregar soporte para el atributo Add
a un tipo de Matrix
que estoy implementando. La sintaxis ideal para dicha adición sería:
let m = m1 + m2 + m3;
donde m1
, m2
, m3
son todas las matrices. Por lo tanto, el tipo de resultado de add
debe ser Matrix
. Algo como lo siguiente sería demasiado críptico:
let m = ((m1 + m2).unwrap() + m3).unwrap()
Al mismo tiempo, la función add()
necesita validar que las dos matrices que se agregan tengan la misma dimensión. Por lo tanto, add()
necesita entrar en pánico si las dimensiones no coinciden. La opción disponible es panic!()
.
Como addendum: la solución propuesta por @ U007D también funciona en doctests:
/// My identity function that panic for an input of 42.
///
/// ```
/// assert_eq!(my_crate::my_func(23), 23);
///
/// let result = std::panic::catch_unwind(|| my_crate::my_func(42));
/// assert!(result.is_err());
/// ```
pub fn my_func(input: u32) -> u32 {
if input == 42 {
panic!("Error message.");
} else {
input
}
}
Como mencionó Francis Gagné en su respuesta, también encuentro que el atributo #[should_panic]
no es lo suficientemente detallado para pruebas más complejas; por ejemplo, si la configuración de mi prueba falla por alguna razón (es decir, he escrito una prueba incorrecta). ), ¡Quiero que el pánico sea considerado un fracaso!
A partir de Rust 1.9.0, std::panic::catch_unwind()
está disponible. Le permite poner el código que espera que entre en pánico en un cierre, y solo los pánicos lanzados por ese código serán considerados "esperados" (es decir, una prueba de aprobación).
#[test]
fn test_something() {
... //<-- Any panics here will cause test failure (good)
let result = std::panic::catch_unwind(|| <expected_to_panic_operation_here>);
assert!(result.is_err()); //probe further for specific error type here, if desired
}
Tenga en cuenta que no puede detectar los pánicos que no se desenrollan (por ejemplo, abortar).
Puede encontrar la respuesta en la sección de testing del libro de Rust. Más específicamente, desea #[should_panic]
atributo #[should_panic]
:
#[test]
#[should_panic]
fn test_invalid_matrices_multiplication() {
let m1 = Matrix::new(3, 4); // assume these are dimensions
let m2 = Matrix::new(5, 6);
m1 * m2
}
Si desea afirmar que solo una parte específica de la función de prueba falla, use task::try()
y verifique que devuelva un Err
, por ejemplo con is_err()
. En las funciones de prueba complejas, esto ayuda a garantizar que la prueba no pase erróneamente debido a una falla temprana.
Several tests en la biblioteca estándar de Rust usan esta técnica.