Skip to content

Testing

Test functions are defined with the #[test] attribute. Within the tests, we use the assert! macro to evaluate a boolean and fail the tests if it does not pass. You can also use assert_eq! and assert_ne! to test equality directly, however the values being tested must implement PartialEq and Debug traits.

Unit Tests

For unit tests, its best to write your tests in the file that it is testing but contain it with a mod tests with the cfg(test) attribute. This will exclude it from the final executable or library. Unit tests also allow you to test private functions, meaning ones that are not pub.

rust
#[cfg(test)]
mod tests {
    use super::*; // Use this to call functions in the current file

    #[test]
    fn it_works() {
        let result = 2 + 2;
        assert_eq!(result, 4);
        assert!(result == 4);
    }

    #[test]
    fn greeting_contains_name() {
        let result = greeting("Carol");
        // Custom failure message
        assert!(
            result.contains("Carol"),
            "Greeting did not contain name, value was `{}`",
            result
        );
    }

    // Will pass if test panics
    #[test]
    #[should_panic]
    fn greater_than_100() {
        // Something illegal
    }
}

Integration Tests

Integration tests live in a separate tests directory at the base of the project. These should test your library from a black box perspective, meaning you use it the same way a consumer would. You do not need to wrap integration tests with a mod tests and #[cfg(tests)] because they are automatically excluded from the build. To include files that provide common functionality to tests but are not tests themselves, you need to make them a module by creating a directory with a mod.rs (ex. tests/common.mod.rs).

rust
use adder; // our lib

mod common;

#[test]
fn it_adds_two() {
    common::setup();
    assert_eq!(4, adder::add_two(2));
}

Documentation Tests

You can define documentation comments with /// which allows you to provide markdown that gets built into an HTML documentation. If you create code blocks, you can write valid rust code and even add assertions to create tests. These will run when you cargo test.

rust
/// Adds one to the number given.
///
/// # Examples
///
/// ```
/// let arg = 5;
/// let answer = my_crate::add_one(arg);
///
/// assert_eq!(6, answer);
/// ```
pub fn add_one(x: i32) -> i32 {
    x + 1
}