Hello, Rustaceans!
Today marks Day 20 of my #100DaysOfRust journey, and I dove into a key feature of Rust that ensures correctness and reliability โ writing tests.
Rust has built-in support for testing with cargo test, and it provides excellent macros, attributes, and tools for writing clear, expressive, and robust test cases.
๐งช Anatomy of a Test Function
Every test function in Rust is marked with the #[test] attribute.
A basic test function:
#[test]
fn it_works() {
// 1. Set up any needed data or state.
let a = 2;
// 2. Run the code you want to test.
let b = a + 2;
// 3. Assert that the result is what you expect.
assert_eq!(b, 4);
}
โ Running Tests
Use this command to run all tests:
cargo test
Rust compiles the tests in a separate test binary and shows clear output about passing or failing tests.
โ๏ธ Checking Conditions with assert!
The assert! macro ensures that a boolean condition is true. If it's not, the test fails.
#[test]
fn assert_macro_example() {
let value = true;
assert!(value); // Passes
}
Fails if:
assert!(false); // panics with default message
You can also add a custom failure message:
assert!(1 + 1 == 3, "Math is broken!");
๐งฎ Testing Equality with assert_eq! and assert_ne!
Rust provides macros to compare values:
-
assert_eq!(a, b)โ passes ifa == b -
assert_ne!(a, b)โ passes ifa != b
#[test]
fn test_equality_macros() {
assert_eq!(2 + 2, 4);
assert_ne!(5, 3);
}
When these fail, Rust shows both the expected and actual values, making debugging easier.
๐ฌ Custom Failure Messages
You can also include custom messages in these macros:
#[test]
fn custom_message_example() {
let result = 2 + 2;
assert_eq!(result, 5, "Expected 5 but got {}", result);
}
Output:
thread 'main' panicked at 'Expected 5 but got 4', src/main.rs:4:5
๐ฅ Testing for Panics with #[should_panic]
Some tests are expected to panic (i.e., crash intentionally under specific conditions).
Use the #[should_panic] attribute:
#[test]
#[should_panic]
fn panics_when_called() {
panic!("This function panics!");
}
Make it more precise using expected:
#[test]
#[should_panic(expected = "Guess value must be less than or equal to 100")]
fn panic_with_message() {
panic!("Guess value must be less than or equal to 100");
}
๐ฏ Writing Tests That Return Result<T, E>
Rust lets you write tests that return Result<(), E> for clearer error reporting.
#[test]
fn test_with_result() -> Result<(), String> {
let value = 2 + 2;
if value == 4 {
Ok(())
} else {
Err("2 + 2 did not equal 4".into())
}
}
This lets you use ? inside your tests, which is especially useful when testing functions that return Result.
๐งช Summary
| Concept | Description |
|---|---|
#[test] |
Marks a function as a unit test |
assert!, assert_eq!, assert_ne!
|
Macros to validate test conditions |
#[should_panic] |
Use when a function should panic |
Result<(), E> return type |
Clean test error reporting and ? usage |
| Custom messages | Improve failure debugging |
๐๏ธ Whatโs Next?
In Day 21, Iโll explore how to organize tests, including modules, integration tests, test hierarchies, and best practices.
Let me know your favorite testing tip in Rust!
Until tomorrow, happy coding! ๐ฆ
Top comments (0)