Rust Testing
Rust has testing built directly into the language and cargo, so you don’t need to reach for a separate library to get started. This page covers just enough to write and run your first tests.
Writing a basic test
Section titled “Writing a basic test”A test is a regular function marked with #[test]:
fn add(a: i32, b: i32) -> i32 { a + b}
#[cfg(test)]mod tests { use super::*;
#[test] fn it_adds_two_numbers() { assert_eq!(add(2, 3), 5); }}A few things worth pointing out:
#[cfg(test)]tells Rust this module is only compiled when running tests — it’s not part of your normal program.use super::*;brings in everything from the parent module (here, theaddfunction), so the test can call it.#[test]marks a specific function as a test thatcargo testshould run.
Running tests
Section titled “Running tests”From your project folder:
cargo testYou’ll see output like:
running 1 testtest tests::it_adds_two_numbers ... ok
test result: ok. 1 passed; 0 failed; 0 ignoredassert! and friends
Section titled “assert! and friends”Three macros cover most of what you’ll need:
#[test]fn checks() { assert!(2 + 2 == 4); // fails the test if the condition is false assert_eq!(2 + 2, 4); // fails if the two values aren't equal assert_ne!(2 + 2, 5); // fails if the two values ARE equal}assert_eq! and assert_ne! are usually preferred over a plain assert!(a == b) — when they fail, they print both values, so you can immediately see what didn’t match instead of just “assertion failed.”
A failing test, and what it looks like
Section titled “A failing test, and what it looks like”fn add(a: i32, b: i32) -> i32 { a + b}
#[cfg(test)]mod tests { use super::*;
#[test] fn this_will_fail() { assert_eq!(add(2, 2), 5); }}test tests::this_will_fail ... FAILED
assertion `left == right` failed left: 4 right: 5That’s exactly the kind of message you want when a test fails — it tells you what your code actually produced versus what the test expected.
Testing that a function panics
Section titled “Testing that a function panics”Sometimes the correct behavior is a panic — say, a function that should refuse invalid input. #[should_panic] tests for that:
fn divide(a: i32, b: i32) -> i32 { if b == 0 { panic!("cannot divide by zero"); } a / b}
#[cfg(test)]mod tests { use super::*;
#[test] #[should_panic] fn dividing_by_zero_panics() { divide(10, 0); }}Why bother writing tests
Section titled “Why bother writing tests”The honest answer: for a short script, you probably won’t. Tests start paying off once code is going to be reused or changed later — they let you refactor with confidence, because cargo test will tell you immediately if you broke something, instead of finding out from a user.
- Mark a function
#[test]to make it a test; run all tests withcargo test. assert!,assert_eq!, andassert_ne!cover most everyday checks — preferassert_eq!/assert_ne!for better failure messages.#[should_panic]tests that a function panics when it’s supposed to.- Tests are most valuable for code you expect to change or reuse later.
Quick check
Section titled “Quick check”Quick check
1. What attribute marks a function as a test that cargo test should run?
2. Why are assert_eq! and assert_ne! usually preferred over a plain assert!(a == b)?
3. What does #[should_panic] do?
Score: 0 / 3