SkillByAIOpen interactive version →

Lesson 23 / 25

Unit Tests With cargo test

Tests next to the code.

#[test], assert_eq!, cfg(test)

Unit tests live in a #[cfg(test)] mod tests block in the same file, so they can test private functions; integration tests live in a tests/ directory and use only the public API. Mark test functions with #[test] and use assert!, assert_eq! and assert_ne!. cargo test compiles and runs them in parallel, and also runs code examples in documentation comments (doc tests).

Quality built into cargo

cargo test, clippy and rustfmt keep Rust code correct and idiomatic.

Figure 8.1 — Tests, lints and checklist.

Three unit tests, run

I ran this with Rust 1.99.0 (cargo run, edition 2024, standard library only). cargo test runs the three tests (percent code, boundary and unknown code) and all pass. The timing was replaced with (time).

pub fn discount(total: u32, code: &str) -> Result<u32, String> {
    match code {
        "" => Ok(total),
        "SAVE10" => Ok(total * 90 / 100),
        "FLAT50" if total >= 50 => Ok(total - 50),
        "FLAT50" => Ok(total),
        other => Err(format!("unknown code {other}")),
    }
}

fn main() {
    println!("{:?}", discount(100, "SAVE10"));
}

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

    #[test]
    fn percent_code() {
        assert_eq!(discount(100, "SAVE10"), Ok(90));
    }

    #[test]
    fn flat_at_boundary() {
        assert_eq!(discount(50, "FLAT50"), Ok(0));
    }

    #[test]
    fn unknown_code_is_error() {
        assert!(discount(100, "BOGUS").is_err());
    }
}

Output:

running 3 tests
test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in (time)

Write doc tests

Examples in /// comments are compiled and run by cargo test, so documentation never goes stale.

Quick check: Why can unit tests in mod tests call private functions?

  • They are in the same module tree as the code they test
  • Rust has no private functions
  • Tests run with root privileges
  • cfg(test) makes everything public everywhere
Answer

They are in the same module tree as the code they test — Child modules see their parent's private items.