CtrlK
BlogDocsLog inGet started
Tessl Logo

testland/cargo-test

Configures and runs Rust's built-in `cargo test` - `#[test]` + `#[should_panic]` + `Result<(), E>` returns; integration tests in `tests/`; doc-tests embedded in `///` comments; `--lib` / `--bins` / `--all-targets` / `--workspace` selection; `cargo bench` (nightly) + Criterion (stable); `cargo test -- --test-threads=1` for serial; `cargo test -- --nocapture` to see println output. Use for any Rust project - testing is built into Cargo, no install needed.

75

Quality

94%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide

SecuritybySnyk

Passed

No findings from the security scan

Overview
Quality
Evals
Security
Files

SKILL.md

name:
cargo-test
description:
Configures and runs Rust's built-in `cargo test` - `#[test]` + `#[should_panic]` + `Result<(), E>` returns; integration tests in `tests/`; doc-tests embedded in `///` comments; `--lib` / `--bins` / `--all-targets` / `--workspace` selection; `cargo bench` (nightly) + Criterion (stable); `cargo test -- --test-threads=1` for serial; `cargo test -- --nocapture` to see println output. Use for any Rust project - testing is built into Cargo, no install needed.

cargo-test

Overview

Per doc.rust-lang.org/book/ch11-00-testing.html:

Rust's testing is built into Cargo. The #[test] attribute marks test functions; cargo test discovers and runs them.

Three test categories per the Rust Book:

CategoryLocationPurpose
Unit testsSame file as code, in #[cfg(test)] mod tests { ... }Test private + internal logic
Integration teststests/ directory at crate rootTest public API as external user
Doc testsInside /// doc commentsVerify documentation examples

How to use

  1. Put unit tests in a #[cfg(test)] mod tests { ... } block next to the code; put cross-crate scenarios in tests/ (Steps 1, 5).
  2. Assert with assert_eq! / assert_ne! / assert!; return Result<(), E> and use ? instead of unwrap() (Steps 2, 4).
  3. Cover error paths with #[should_panic(expected = "...")], and mark slow/networked tests #[ignore = "reason"] (Steps 3, 8).
  4. Run cargo test --all-targets --workspace locally; filter by name pattern and add -- --nocapture to see println! output (Steps 1, 7).
  5. Keep documented examples honest with doc tests in /// comments, verified by cargo test --doc (Step 6).
  6. Gate coverage and track performance with cargo llvm-cov and Criterion (see references/coverage-and-benchmarks.md).
  7. Wire the same commands into CI so every push runs tests, doc tests, and the coverage gate (Step 10).

Step 1 - Unit tests

// src/math.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(1, 2), 3);
    }

    #[test]
    fn handles_zero() {
        assert_eq!(add(0, 0), 0);
    }
}

Run:

cargo test                 # all tests
cargo test add             # filter by name pattern
cargo test --lib           # only unit tests in lib
cargo test --bins          # binary tests
cargo test --all-targets   # everything
cargo test --workspace     # multi-crate workspace

Step 2 - Assertion macros

assert!(condition);
assert!(condition, "format message: {}", value);
assert_eq!(actual, expected);
assert_eq!(actual, expected, "with message");
assert_ne!(actual, unexpected);

// Custom error message:
assert!(actual > 0, "Expected positive, got {}", actual);

For richer assertions, the pretty_assertions crate provides diff-rich macros:

use pretty_assertions::assert_eq;
assert_eq!(actual_complex_struct, expected_complex_struct);
// shows colorized diff on failure

Step 3 - #[should_panic]

#[test]
#[should_panic]
fn panics_on_negative() {
    sqrt(-1.0);
}

#[test]
#[should_panic(expected = "negative")]
fn specific_panic_message() {
    sqrt(-1.0);
    // panics with message containing "negative"
}

Step 4 - Result return for ?-style propagation

#[test]
fn parses_config() -> Result<(), Box<dyn Error>> {
    let cfg = Config::from_file("test/fixtures/config.toml")?;
    assert_eq!(cfg.port, 8080);
    Ok(())
}

Test passes if Ok(()); fails if Err(...). Avoids unwrap() boilerplate; allows ? operator in test bodies.

Step 5 - Integration tests

my-crate/
  src/
    lib.rs
  tests/
    integration_test.rs    # automatically discovered
    common/
      mod.rs               # shared helpers (note: NO mod.rs in tests/ root)
// tests/integration_test.rs
use my_crate::Calculator;

#[test]
fn end_to_end() {
    let c = Calculator::new();
    assert_eq!(c.add(1, 2), 3);
}

mod common;   // shared test helpers from tests/common/mod.rs

Each file in tests/ compiles to its own binary - slower but better-isolated than unit tests.

Step 6 - Doc tests

/// Adds two numbers.
///
/// # Examples
///
/// ```
/// use my_crate::math::add;
/// assert_eq!(add(1, 2), 3);
/// ```
pub fn add(a: i32, b: i32) -> i32 {
    a + b
}

cargo test --doc runs only doc tests; cargo test runs everything including docs. The example IS the test - drift between docs + implementation is caught.

# Examples heading is convention; required for cargo doc HTML rendering to show the example.

Step 7 - Common test runner flags

cargo test -- --test-threads=1           # serial (single-threaded)
cargo test -- --nocapture                 # show stdout (println in tests)
cargo test -- --show-output               # show stdout for passed tests too
cargo test -- --ignored                   # only run #[ignore]-marked tests
cargo test -- --include-ignored           # run both ignored + normal
cargo test -- --list                      # list tests without running
cargo test some_pattern -- --exact        # exact match (no substring)

Step 8 - #[ignore] for slow tests

#[test]
#[ignore = "Requires network access"]
fn integration_with_external_api() {
    // ...
}

Run via cargo test -- --include-ignored.

Step 9 - Coverage and benchmarks

Both need an extra crate installed (cargo-llvm-cov / cargo-tarpaulin for coverage; Criterion for benchmarks on stable). Full commands, the Cargo.toml bench wiring, and the Criterion example are in references/coverage-and-benchmarks.md.

Step 10 - CI integration

- run: cargo test --all-targets --workspace
- run: cargo test --doc                # explicit doc tests
- run: cargo install cargo-llvm-cov
- run: cargo llvm-cov --lcov --output-path coverage.lcov
- uses: codecov/codecov-action@v4
  with: { files: coverage.lcov }

Worked example

A crate exposes add(a, b) in src/math.rs and you need it tested before release.

  1. Add a #[cfg(test)] mod tests block with adds_two_numbers and handles_zero, each using assert_eq! (Step 1).
  2. Add a doc test in the /// comment on add so the documented example is executed (Step 6).
  3. Run cargo test --all-targets: the unit block prints test result: ok. 2 passed, then Doc-tests my_crate ... 1 passed.
  4. Add cargo llvm-cov --fail-under-lines 80; it reports add fully covered and exits 0 (see references/coverage-and-benchmarks.md).
  5. CI runs cargo test --all-targets --workspace plus the coverage gate on every push (Step 10).

Result: unit, doc, and coverage checks are all green - the function is release-ready.

Anti-patterns

Anti-patternWhy it failsFix
Skip --all-targetsDoc tests + bench + examples not runAlways --all-targets (Step 1)
Use unwrap() in test bodiesTest failure message is "called unwrap on None"; uselessUse Result<(), E> return + ? (Step 4)
#[ignore] without reasonForgotten ignored testsAlways include = "reason" (Step 8)
assert!(x == y) instead of assert_eq!Loses diff in failureUse assert_eq! (Step 2)
Skip Criterion for performance workStdlib #[bench] is nightly-only; CI breaksUse Criterion on stable (see references/coverage-and-benchmarks.md)

Limitations

  • No fixture concept beyond mod tests shared state.
  • Doc tests slow to compile (each runs as separate doctest binary).
  • No mocking library in stdlib - mockall is the community standard for trait mocking.
  • No parametrize beyond hand-rolled loops or rstest (see rstest-tests).

References

  • rust-test - Rust Book Chapter 11 (testing)
  • doc.rust-lang.org/cargo/commands/cargo-test.html - cargo test reference
  • bheisler.github.io/criterion.rs - Criterion docs
  • crates.io/crates/cargo-llvm-cov - coverage tool
  • go-test, ginkgo-tests, rstest-tests - sister tools
  • proptest-testing (qa-property-based) - Rust property-based
  • test-code-conventions (qa-test-review)

SKILL.md

tile.json