C.W.K.
Stream
Lesson 04 of 06 · published

Testing — Built In

~11 min · tooling, testing, doctest

Level 0Rust Curious
0 XP0/80 lessons0/19 achievements
0/100 XP to next level100 XP to go0% complete

Testing is built into the language and Cargo — no framework to install, no config to write. cargo test just works, and Rust supports three flavors of test out of the box.

Unit tests

Unit tests live in the same file as the code they test, in a #[cfg(test)] mod tests block. Functions marked #[test] are run by cargo test. Because they're in the module, they can test private functions — a deliberate Rust choice many languages can't match. Use assert!, assert_eq!, and friends for the checks.

Integration tests

Integration tests live in a top-level tests/ directory, each file a separate crate that uses your library through its public API only — exactly as a real consumer would. They verify your crate works from the outside. The split is intentional: unit tests check internals, integration tests check the contract.

Tests are first-class, not bolted on. #[test], cargo test, and #[cfg(test)] are language and tooling features — no third-party framework, no setup. That low friction is why idiomatic Rust is heavily tested: when writing a test costs nothing but the test itself, you write more of them.

Doctests

The third flavor is uniquely Rust: code examples in your /// doc comments are compiled and run as tests. A wrong example fails cargo test, so your documentation can't drift out of sync with your code. It's the antidote to stale docs — the examples are guaranteed to work because they're tested on every run.

Code

Unit test, doctest, all run by cargo test·rust
pub fn add(a: i32, b: i32) -> i32 {
    a + b
}

/// Doubles a number.
///
/// ```
/// assert_eq!(my_crate::double(21), 42); // this example is RUN by cargo test
/// ```
pub fn double(n: i32) -> i32 { n * 2 }

#[cfg(test)] // compiled only during testing
mod tests {
    use super::*;
    #[test]
    fn add_works() {
        assert_eq!(add(2, 2), 4); // a unit test — can see private items too
    }
}

External links

Exercise

Write a small library function, then add: a unit test in a #[cfg(test)] mod tests block, a doctest in its /// comment, and (optionally) an integration test in tests/. Run cargo test and watch all three run. Deliberately break the doctest example and confirm cargo test catches it.
Hint
Unit tests verify internals (can see private items); doctests verify your documentation's examples actually work; integration tests verify the public API from outside. Breaking the doctest proves your docs can't silently go stale.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.