Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Adding tests

Tests can be included in the same file as the code using the #[cfg(test)] module. Each test function is annotated with #[test]. Inside a test, you can use assert_eq!, assert!, or similar macros to validate expected behavior.

The full test module can be seen below. We go through each of them in the sequel of this section.

Full test module
#![allow(unused)]
fn main() {
#[cfg(test)]
mod tests {
    use super::*;
    use ndarray::array;

    #[test]
    fn test_ridge_estimator_constructor() {
        let model = RidgeEstimator::new();
        assert_eq!(model.beta, None, "beta is expected to be None");
    }

    #[test]
    fn test_unfitted_estimator() {
        let model = RidgeEstimator::new();
        let x: Array1<f64> = array![1.0, 2.0];
        let result: Result<Array1<f64>, String> = model.predict(&x);

        assert!(result.is_err());
        assert_eq!(result.unwrap_err(), "Model not fitted");
    }

    #[test]
    fn test_ridge_estimator_solution() {
        let x: Array1<f64> = array![1.0, 2.0];
        let y: Array1<f64> = array![0.1, 0.2];
        let true_beta: f64 = 0.1;
        let lambda2: f64 = 0.0;

        let mut model = RidgeEstimator::new();
        model.fit(&x, &y, lambda2);

        assert!(model.beta.is_some(), "beta is expected to be Some(f64)");

        assert!(
            (true_beta - model.beta.unwrap()).abs() < 1e-6,
            "Estimate {} not close enough to true solution {}",
            true_beta,
            model.beta.unwrap()
        );
    }
}
}

Recall that tests can be executed by running cargo test.

Testing the constructor

As a first simple test, we check that beta of a new RidgeEstimator is None.

#![allow(unused)]
fn main() {
#[test]
fn test_ridge_estimator_constructor() {
    let model = RidgeEstimator::new();
    assert_eq!(model.beta, None, "beta is expected to be None");
}
}

Testing an unfitted model

As a second test, we check that the predict function returns error if the model is unfitted.

#![allow(unused)]
fn main() {
#[test]
fn test_unfitted_estimator() {
    let model = RidgeEstimator::new();
    let x: Array1<f64> = array![1.0, 2.0];
    let result: Result<Array1<f64>, String> = model.predict(&x);

    assert!(result.is_err());
    assert_eq!(result.unwrap_err(), "Model not fitted");
}
}

Testing a fitted model

Finally, we check that a fitted model returns a Some(f64) and that the solution is close to the known value.

#![allow(unused)]
fn main() {
#[test]
fn test_ridge_estimator_solution() {
    let x: Array1<f64> = array![1.0, 2.0];
    let y: Array1<f64> = array![0.1, 0.2];
    let true_beta: f64 = 0.1;
    let lambda2: f64 = 0.0;

    let mut model = RidgeEstimator::new();
    model.fit(&x, &y, lambda2);

    assert!(model.beta.is_some(), "beta is expected to be Some(f64)");

    assert!(
        (true_beta - model.beta.unwrap()).abs() < 1e-6,
        "Estimate {} not close enough to true solution {}",
        true_beta,
        model.beta.unwrap()
    );
}
}