Problema con los resultados de las pruebas unitarias en Rust

Publicado por Brisa
hace 1 año

Hola a todos,

Estoy teniendo problemas al ejecutar las pruebas unitarias en mi proyecto de Rust. El código en sí funciona perfectamente, pero algunas de las pruebas unitarias están fallando y estoy teniendo dificultades para comprender los resultados que me arroja Rust.

Aquí está el código de una de las pruebas que está fallando:

struct Calculator {
    value: i32,
}

impl Calculator {
    fn new() -> Calculator {
        Calculator { value: 0 }
    }

    fn add(&mut self, num: i32) {
        self.value += num;
    }

    fn multiply(&mut self, num: i32) {
        self.value *= num;
    }

    fn subtract(&mut self, num: i32) {
        self.value -= num;
    }

    fn divide(&mut self, num: i32) {
        if num == 0 {
            panic!("Division by zero error!");
        }

        self.value /= num;
    }

    fn get_value(&self) -> i32 {
        self.value
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_calculator_operations() {
        let mut calc = Calculator::new();

        calc.add(5);
        assert_eq!(calc.get_value(), 5);

        calc.multiply(2);
        assert_eq!(calc.get_value(), 10);

        calc.subtract(3);
        assert_eq!(calc.get_value(), 7);

        calc.divide(0); // Este es el test que falla
        assert_eq!(calc.get_value(), 7);
    }
}

La prueba test_calculator_operations verifica que las operaciones de suma, multiplicación y resta se realicen correctamente en la calculadora. Sin embargo, la prueba de división por cero (calc.divide(0)) falla, como se esperaba. Pero el resultado que me arroja Rust no es muy descriptivo y no puedo entender cuál es el problema exacto.

Este es el resultado de las pruebas unitarias:

running 1 test
test tests::test_calculator_operations ... FAILED

failures:

---- tests::test_calculator_operations stdout ----
        thread 'tests::test_calculator_operations' panicked at 'Division by zero error!', src/main.rs:24:13
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

failures:
    tests::test_calculator_operations

test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out

error: test failed, to rerun pass '--lib'

Mi pregunta es: ¿Cómo puedo obtener una descripción más detallada del error que ocurrió durante la ejecución de la prueba unitaria? ¿Hay alguna manera de obtener una traza de pila o más información sobre el error para poder solucionarlo?

Agradezco cualquier ayuda que puedan brindarme para entender mejor los errores en las pruebas unitarias de Rust.

¡Gracias de antemano!

Rust pruebas unitarias resultados
Respuesta de Gordon Shumway
hace 1 año

¡Hola Brisa!

En efecto, la prueba test_calculator_operations está diseñada para fallar cuando intentas hacer una división por cero, ya que en el método divide de tu Calculator has puesto una llamada a panic! en ese caso.

La prueba falla porque está provocando exactamente el comportamiento que programaste: un pánico cuando hay una división por cero. Rust te informa de que la prueba falló debido a ese pánico, lo cual es el comportamiento esperado según tu implementación actual.

Si lo que quieres es una descripción más detallada del error para entender el pánico, lo que puedes hacer es ejecutar las pruebas con la variable de entorno RUST_BACKTRACE establecida en 1. Eso proporcionará una traza de pila completa en el momento del pánico, lo que puede ayudarte a encontrar no sólo la línea exacta del código que causó el error, sino también las llamadas a funciones que llevaron a ese punto.

Puedes hacerlo de la siguiente manera desde la línea de comandos:

RUST_BACKTRACE=1 cargo test

Sin embargo, si quieres que la prueba pase incluso en el caso de división por cero, puedes modificar el test para que maneje el pánico esperado utilizando un bloque std::panic::catch_unwind, que captura el pánico sin que la prueba falle:

#[test]
fn test_calculator_operations() {
    let mut calc = Calculator::new();

    calc.add(5);
    assert_eq!(calc.get_value(), 5);

    calc.multiply(2);
    assert_eq!(calc.get_value(), 10);

    calc.subtract(3);
    assert_eq!(calc.get_value(), 7);

    let result = std::panic::catch_unwind(|| {
        calc.divide(0); // Intentamos dividir por 0, lo cual debería causar un pánico
    });

    assert!(result.is_err()); // Confirmamos que hubo un pánico, como se esperaba

    // Opcionalmente, podrías quitar esta línea si ya no te interesa verificar el valor después del pánico
    // assert_eq!(calc.get_value(), 7); // Esto no se ejecutará, dado que el hilo de prueba habrá entrado en pánico
}

Con esto, tu prueba comprueba que se produce un pánico al intentar una división por cero, lo cual es esperado y la considera una situación "correcta", resultando así en que la prueba pase exitosamente.

¡Espero que esto te ayude a comprender y manejar los errores de las pruebas en Rust!