What You'll Learn
Testing and documentation are the most direct ways to make code trustworthy. We'll walk through the cargo test workflow, how to build #[test] functions, and how to leave runnable examples in doc comments.
Exploring cargo test
Any Rust project starts with a working cargo test setup by default.
cargo new calculator
cd calculator
cargo test
The template already includes a sample test, so you'll immediately see the runner execute. As long as nothing fails, you'll get the runtime, test count, and package name instead of an error report.
Writing #[test] Functions
Let's add a library function and a matching test to src/lib.rs.
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn adds_two_numbers() {
assert_eq!(add(2, 3), 5);
}
}
- The
#[cfg(test)]module compiles only duringcargo test, keeping the release binary slimmer. - Functions tagged with
#[test]don't return values, and any panic marks the test as failed.
The assert_eq! macro compares the actual and expected values. When it fails, it shows both values plus the source location, which makes debugging quick.
Code inside doc comments is also a form of testing. Every documented example doubles as runnable verification, and that's one of Rust's biggest wins.
Testing Edge Cases
When you write multiple tests for the same function, choose descriptive scenario names so future refactors keep their meaning.
#[test]
fn add_handles_negative() {
assert_eq!(add(-3, 1), -2);
}
#[test]
fn add_with_zero_returns_other() {
assert_eq!(add(0, 7), 7);
}
If someone can infer the inputs just by reading the test names, they'll also understand failure logs more quickly.
Doc Comments and Examples
Any library you expect others to consume needs doc comments (///). Embed code blocks inside those comments, and cargo test will execute them for you.
/// Returns the sum of two integers.
///
/// # Examples
///
/// ```
/// use calculator::add;
/// assert_eq!(add(2, 2), 4);
/// ```
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
Doctests are lifesavers when maintaining real usage examples. If the implementation changes, outdated samples fail immediately, keeping documentation and code in sync.
cargo doc --open
Run the following command whenever you want an HTML preview of your docs:
cargo doc --open
It documents the public API of your project and opens it in the default browser. Items that aren't pub stay hidden, so be intentional about what you expose.
Common Pitfalls
- Declaring parameters on a
#[test]function causes a compile error; tests can't take arguments. - Async tests need a runtime such as
#[tokio::test]. We focus on synchronous tests here. - Use
cargo test -- --nocaptureto seeprintln!output; the default hides logs when tests pass. - If interleaved output is confusing, run
cargo test -- --test-threads=1to execute tests sequentially.
Practice
- Implement
subtractand add two tests that cover positive and negative inputs. - Execute only one test with
cargo test add_handles_negative -- --nocaptureand inspect the log. - Add a
# Panicssection to the doc comments to describe when the function panics.
Wrap-Up
Tests and doc comments are the first lines of defense for a reliable Rust codebase. cargo test works out of the box, and examples inside /// comments execute as real tests. Next time, we'll run this code safely across multiple threads as we introduce concurrency basics.
💬 댓글
이 글에 대한 의견을 남겨주세요