Unit Testing

assert!

The assert! macro evaluates a boolean expression at runtime and panics if the expression evaluates to false. It is the foundational assertion macro in Rust's standard library for verifying invariants, boolean predicates, and pattern checks via matches!.

assert!(condition)
assert!(condition, "format string {}", arg)
          |
          +-- condition == true   --> Continues execution normally
          +-- condition == false  --> Panics with file, line, column, and message

Basic Usage and Custom Diagnostic Messages

When called with a single boolean expression (assert!(expr)), a failure prints the stringified source expression (assertion failed: expr). Passing a format string and arguments as subsequent parameters (assert!(expr, "context: {val}")) formats a detailed diagnostic message only when the assertion fails.

fn is_sorted_ascending(slice: &[i32]) -> bool {
    slice.windows(2).all(|w| w[0] <= w[1])
}

fn main() {
    let data = [2, 4, 8, 16, 32];

    // 1. Simple boolean assertion
    assert!(!data.is_empty());

    // 2. Assertion with lazy formatted diagnostic message
    assert!(
        is_sorted_ascending(&data),
        "expected ascending order, but got {data:?}"
    );

    // 3. Combining `assert!` with `matches!` when a type does not implement PartialEq
    let result: Result<i32, &str> = Ok(42);
    assert!(
        matches!(result, Ok(n) if n > 0),
        "expected positive Ok value, got {result:?}"
    );

    println!("All assert! checks succeeded");
}
All assert! checks succeeded

Inspecting assert! Failure Output

When an assert! fails inside a test or main, the panic message reports the source file, line number, column number, and custom message:

fn main() {
    let temperature = 105;
    assert!(
        (0..=100).contains(&temperature),
        "temperature {temperature}°C is outside liquid water range (0..=100°C)"
    );
}
thread 'main' panicked at src/main.rs:3:5:
temperature 105°C is outside liquid water range (0..=100°C)

assert! vs debug_assert!

Macro Active in Debug & cargo test? Active in Release (-C opt-level)? Primary Use Case
assert! Yes Yes Unit tests, security/safety checks, and invariants that must always hold in production.
debug_assert! Yes No (compiled out unless -C debug-assertions) Expensive $O(n)$ internal invariant checks on hot paths.

Never place an expression with required side effects inside debug_assert!(iter.next().is_some()), because the expression is not evaluated at all in release builds.