test

fohte's avatarfrom fohte

Use this skill when writing or running tests. Enforces rstest for parametrized tests and DRY test patterns. Use when creating new tests, fixing test failures, or improving test coverage.

⭐0stars🔀0forks📁View on GitHub🕐Updated Jan 10, 2026

When & Why to Use This Skill

This Claude skill optimizes Rust development workflows by enforcing best practices in automated testing. It leverages the rstest framework to implement DRY (Don't Repeat Yourself) principles through parametrized tests and fixtures. By integrating tools for execution and coverage analysis, it helps developers create maintainable test suites, quickly resolve regressions, and ensure high code quality through comprehensive coverage metrics.

Use Cases

  • Refactoring repetitive test cases into clean, parametrized tests using the rstest crate to reduce boilerplate code.
  • Automating the debugging process for failed tests by analyzing logs and applying fixes directly within the Rust environment.
  • Measuring and improving project test coverage using cargo-llvm-cov to identify untested logic paths.
  • Setting up complex test environments using reusable fixtures to ensure consistent state across multiple test scenarios.
  • Implementing combinatorial testing with values and cases to validate software behavior across diverse input sets.
nametest
descriptionUse this skill when writing or running tests. Enforces rstest for parametrized tests and DRY test patterns. Use when creating new tests, fixing test failures, or improving test coverage.
allowed-toolsRead, Grep, Glob, Edit, Write, Bash(cargo test:*)

Testing with rstest

This project uses rstest for DRY, parametrized tests.

Running Tests

cargo test                     # Run all tests
cargo test <test_name>         # Run specific test
cargo test -- --nocapture      # Show stdout

Coverage

Use cargo-llvm-cov to measure test coverage locally:

cargo llvm-cov                           # Run tests with coverage (text summary)
cargo llvm-cov --html                    # Generate HTML report in target/llvm-cov/html/
cargo llvm-cov --lcov --output-path lcov.info  # Generate LCOV format (used in CI)

Coverage is automatically measured and uploaded to Codecov in CI.

Writing Tests

Always prefer rstest over plain #[test]

Use #[rstest] with #[case] for multiple inputs:

use rstest::*;

#[rstest]
#[case::empty("", true)]
#[case::whitespace("   ", true)]
#[case::valid("hello", false)]
fn test_is_blank(#[case] input: &str, #[case] expected: bool) {
    assert_eq!(is_blank(input), expected);
}

Use fixtures for shared setup

#[fixture]
fn repository() -> InMemoryRepository {
    let mut r = InMemoryRepository::default();
    // setup
    r
}

#[rstest]
fn test_find(repository: InMemoryRepository) {
    // repository is automatically injected
}

Combine cases with values

#[rstest]
#[case::admin(User::Admin)]
#[case::guest(User::Guest)]
fn test_access(
    #[case] user: User,
    #[values("read", "write", "delete")] action: &str,
) {
    // Generates 6 tests: admin+read, admin+write, ...
}

Use indoc for multiline test input

use indoc::indoc;

#[rstest]
#[case::with_frontmatter(
    indoc! {r#"
        ---
        title: "Test"
        ---
        Body content
    "#},
    "Test",
    "Body content\n"
)]
fn test_parse(#[case] input: &str, #[case] title: &str, #[case] body: &str) {
    let doc = parse(input);
    assert_eq!(doc.title, title);
    assert_eq!(doc.body, body);
}

Test Naming

  • Use #[case::descriptive_name] for named cases
  • Test function: test_<function>_<scenario> or should_<behavior>

DRY Principles

  1. Extract common assertions into helper functions
  2. Use fixtures for repeated setup
  3. Parametrize similar tests with #[case]
  4. Use #[values] for combinatorial testing