Testing

Everyone's favorite topic! Writing tests!

It's actually pretty exciting with Rust, since you have good tools to make testing pretty easy. It's all built-in out of the box.

Unit tests

The typical way to write tests with Rust is to create a child module called test, import from the parent, and test things. These are written in a way that they're only compiled if a flag is enabled for tests, so they're not included in your release builds. Handy!

Let's see an example.

We'll go back to the same example we had of a super useful addition function. Then we can write a test to make sure it adds things correctly.

#![allow(unused)]
fn main() {
pub fn plus(x: i32, y: i32) -> i32 {
    x + y
}

// this cfg says "only compile this if the test compile option is on"
#[cfg(test)]
// by convention we call this "tests" but it doesn't need to be
mod tests {
    // usually you avoid importing all, but it's idiomatic for tests
    use super::*;

    // this is how we mark this function as a test
    #[test]
    fn adds_small_numbers() {
        let x = 10;
        let y = 20;
        let expected = 30;
        assert_eq!(plus(x, y), expected, "should add up correctly");
    }

    // this test WILL FAIL because the integers roll over
    #[test]
    fn adds_big_numbers() {
        let x = 2_000_000_000;
        let y = 2_000_000_000;
        assert!(plus(x, y) > 0, "result should be positive");
    }
}
}

Then to run the tests, you run cargo test and it should find and execute all your tests (or your compile errors).

Integration tests

Just as with unit tests, you can write integration tests. The main difference is that these tests can only consume the public API that you provide.

Any file you put in the tests/ directory will be treated as an integration test.

Let's say you have your plus function in a crate, then you could open tests/my_test.rs and write:

#![allow(unused)]
fn main() {
use my_library::plus;

#[test]
fn test_addition() {
    assert_eq!(plus(10, 20), 30);
}
}

Doc tests

Rust also gives you facilities to write tests directly in your documentation. You can put a docstring on a function, module, etc. with /// (as opposed to the usual // to start a comment). If you put code blocks (with the markdown style ```), it will be compiled and run when you run cargo test. (This also has the neat side effect of making your documentation code examples automatically break the build if they are out of date!)

Here's an example for, again, our plus function.

#![allow(unused)]
fn main() {
/// Adds together two numbers, and doesn't handle rollover.
///
/// ```
/// use playground::plus;
/// assert_eq!(30, plus(10, 20));
/// ```
pub fn plus(x: i32, y: i32) -> i32 { x + y }
}