🎓 A1Learner
🔍

Rust Doctest Options

Doctest annotations are words after the opening ``` fence that steer the test run of a doc comment code block. One word can skip the test.

Pin the edition

This block is always compiled as 2021 code:

/// ```edition2021
/// assert_eq!(2 + 2, 4);
/// ```

Skip on one kind of machine

This block is ignored on x86_64 targets only:

/// ```ignore-x86_64
/// assert!(true);
/// ```

no_run: compile, never run

This block must compile, but running it would never finish — so the tests only compile it:

/// ```no_run
/// loop {}
/// ```

compile_fail: it must not compile

This block is a deliberate mistake. The test passes only because the compiler rejects it:

/// ```compile_fail
/// let x: i32 = "text";
/// ```

Using ? inside a doctest

A doctest has no main of its own, so ? has nowhere to return to. Give it one — and hide the wrapper lines with # so readers never see them.

/// ```
/// use std::num::ParseIntError;
/// # fn main() -> Result<(), ParseIntError> {
/// let n: i32 = "42".parse()?;
/// assert_eq!(n, 42);
/// # Ok(())
/// # }
/// ```

Example

/// Adds two numbers and returns the sum.
///
/// # Examples
/// A plain block is compiled and run as a test:
/// ```
/// assert_eq!(add(2, 3), 5);
/// ```
/// This block must panic to pass:
/// ```should_panic
/// panic!("shown on purpose");
/// ```
fn add(a: i32, b: i32) -> i32 { a + b }
fn main() { println!("add(2, 3) = {}", add(2, 3)); }

Key points

  • A doctest annotation is a word that steers how a doc code block is tested.
  • Write the annotation right after the opening fence: ```no_run — and several annotations can be combined with commas
  • Use ```ignore for an example that cannot run yet.
  • It is never compiled.
  • The page still shows it.
  • But nothing checks it.
  • So it can quietly rot
  • Use ```text for blocks that are not Rust at all.
  • A terminal command is one example.
  • Sample output is another.
  • Then rustdoc never tries to test them
  • cargo test --doc reports each doctest by its kind.
  • The kinds are ok and ignored.
  • They include compile, should panic, and compile fail.
  • It is a quick way to check promises.
  • You can see every promise being kept
  • The line itself may need to begin with a single #.
  • Then start the line with ##.
  • The first # is the escape.
  • So ##tag runs.
  • It renders as #tag

In this example, one small function carries two doctests with different promises. The first block is plain: cargo test compiles it and runs it, and assert_eq! checks that add(2, 3) equals 5. The second block carries should_panic: its panic! is not a failure but the whole point, so the test passes because the code panics. main itself just prints add(2, 3) = 5, agreeing with the first doctest. In a real library, cargo test --doc would report both blocks as ok. One is a normal run. One is "should panic". The plain block must first bring add into scope. A doctest compiles as its own little program. So real libraries add a hidden line. The line looks like # use my_crate::add;. It sits at the top of the block. The # keeps that line off the page.

Note

Annotations are promises the test suite keeps checking — except ignore and text, which promise nothing.

Prefer no_run or compile_fail whenever the code can still be compile-checked.

Try it Yourself

Edit the code, then press Run.

Running is simulated · Rust Playground

Exercise

An example opens a network connection and waits for an answer. It must keep compiling, but tests should never actually run it. Which annotation fits?