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)