24.2 Writing Basic Tests
In Rust, tests are functions marked with the #[test]
attribute. The test runner executes these functions. A test passes if its function completes execution without panicking; it fails if the function panics.
24.2.1 The #[test]
Attribute
fn add(a: i32, b: i32) -> i32 {
a + b
}
#[test]
fn test_addition_success() {
let result = add(2, 2);
assert_eq!(result, 4); // Passes if 2 + 2 == 4
}
#[test]
fn test_addition_failure() {
let result = add(2, 2);
// This assertion fails because 4 != 5, causing the function to panic.
assert_eq!(result, 5);
}
- The
#[test]
attribute identifiestest_addition_success
andtest_addition_failure
as test functions. - Test functions typically take no arguments and return
()
(the unit type), although returningResult
is also possible (see Section 24.5.2).
24.2.2 Assertion Macros
Rust’s standard library provides macros for asserting conditions within tests:
assert!(expression)
: Panics ifexpression
evaluates tofalse
. Suitable for simple boolean conditions.assert_eq!(left, right)
: Panics ifleft != right
. This is the most frequently used assertion. Requires that the types implement thePartialEq
andDebug
traits (the latter for printing values upon failure).assert_ne!(left, right)
: Panics ifleft == right
. Also requiresPartialEq
andDebug
.
These macros can accept optional arguments (after the mandatory ones) for a custom failure message, formatted using the same syntax as println!
:
#[test]
fn test_custom_message() {
let width = 15;
assert!(width >= 0 && width <= 10, "Width ({}) is out of range [0, 10]", width);
}
24.2.3 Running Tests with cargo test
The command cargo test
compiles the project in a test configuration (which includes code marked with #[cfg(test)]
) and runs all discovered tests (unit, integration, and documentation tests).
$ cargo test
Compiling my_crate v0.1.0 (...)
Finished test [unoptimized + debuginfo] target(s) in ...s
Running unittests src/lib.rs (...)
running 2 tests
test tests::test_addition_success ... ok
test tests::test_addition_failure ... FAILED
failures:
---- tests::test_addition_failure stdout ----
thread 'tests::test_addition_failure' panicked at src/lib.rs:16:5:
assertion failed: `(left == right)`
left: `4`,
right: `5`
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
failures:
tests::test_addition_failure
test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in ...s
error: test failed, to rerun pass '--lib'
The output clearly shows test progress, failures with assertion details (values, file, line number), and a final summary.