Skip to content

Testing — #[test], cargo test, and Doctests

In TypeScript you reach for Jest (or Vitest) and write describe/it/expect blocks in separate .test.ts files. Rust’s test runner is built into the compiler: annotate any function with #[test] and cargo test will discover and run it automatically — no third-party crate required.

TypeScript
// math.ts
export function add(a: number, b: number): number {
return a + b;
}
// math.test.ts
import { add } from './math';
test('adds two numbers', () => {
expect(add(3, 4)).toBe(7);
});
Rust
// src/lib.rs (tests live in the same file)
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
#[cfg(test)]
mod tests {
use super::*; // import everything from the parent module
#[test]
fn test_add() {
assert_eq!(add(3, 4), 7);
}
#[test]
fn test_add_negative() {
assert_eq!(add(-1, 1), 0);
}
}

The #[cfg(test)] attribute means the test module is only compiled when running cargo test — it is stripped from release builds automatically.

Terminal window
cargo test # run all tests in the project
cargo test test_add # run tests whose name contains "test_add"
cargo test -- --nocapture # show println! output during tests
cargo test -- --test-threads=1 # run tests sequentially (no parallelism)
assert_eq!(left, right); // expect(a).toBe(b)
assert_ne!(left, right); // expect(a).not.toBe(b)
assert!(condition); // expect(condition).toBeTruthy()
assert!(condition, "message {}", 42); // with a custom failure message
#[test]
#[should_panic(expected = "divide by zero")]
fn test_divide_by_zero() {
divide(10, 0); // this function should panic
}

Rust can run code examples written in /// doc comments. They serve as both documentation and tests.

/// Adds two integers together.
///
/// # Examples
///
/// ```
/// let result = my_crate::add(2, 3);
/// assert_eq!(result, 5);
/// ```
pub fn add(a: i32, b: i32) -> i32 {
a + b
}

Run them with the same command: cargo test.

Playground note: #[test] functions require the cargo test binary context and cannot run in the browser playground. The snippet below uses fn main with assert_eq! to demonstrate the same logic — run cargo test locally for the full test suite experience.

fn add(a: i32, b: i32) -> i32 {
a + b
}
fn is_even(n: i32) -> bool {
n % 2 == 0
}
fn main() {
// Manually exercise the logic (in real projects, use #[test])
assert_eq!(add(3, 4), 7);
assert_eq!(add(-1, 1), 0);
assert!(is_even(4));
assert!(!is_even(7));
println!("All assertions passed!");
}
Which attribute marks a Rust function as a test?
What does `#[cfg(test)]` do?
Which macro is equivalent to Jest's `expect(a).toBe(b)`?
Where do Rust integration tests live?