agentsclimarketplace

Rust testing

Skill Mattakushi432/Claude-Code-Skills-Custom-DevTools-Pack/plugins/devtools-pack/skills/rust-testing

When to activate: Rust tests, unit tests, integration tests, doc tests, benchmarks, proptest, test helpers, test organizationFrom its SKILL.md

Install
npx -y skills add Mattakushi432/Claude-Code-Skills-Custom-DevTools-Pack --skill rust-testing

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

4.8 KB, ~1.3k tokens by cl100k_base, as published. Nobody here has run it

Rust Testing Patterns

Unit Tests

Place unit tests in the same file as the code under test inside a #[cfg(test)] module.

pub fn add(a: i32, b: i32) -> i32 { a + b }

pub fn divide(a: f64, b: f64) -> Option<f64> {
    if b == 0.0 { None } else { Some(a / b) }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn add_positive_numbers() {
        assert_eq!(add(2, 3), 5);
    }

    #[test]
    fn divide_by_zero_returns_none() {
        assert_eq!(divide(10.0, 0.0), None);
    }

    #[test]
    #[should_panic(expected = "index out of bounds")]
    fn panics_on_bad_index() {
        let v: Vec<i32> = vec![];
        let _ = v[0];
    }
}

Integration Tests

Live in the tests/ directory at the crate root; each file is a separate crate.

// tests/api_tests.rs
use my_crate::{App, Config};

fn setup_app() -> App {
    App::new(Config { db_url: ":memory:".into(), port: 0 })
}

#[test]
fn creates_user_and_retrieves_it() {
    let app = setup_app();
    let id = app.create_user("[email protected]").unwrap();
    let user = app.get_user(id).unwrap();
    assert_eq!(user.email, "[email protected]");
}

// Shared test helpers go in tests/common/mod.rs

Doc Tests

Code examples in doc comments are compiled and run as tests.

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

Property-Based Testing with proptest

# Cargo.toml
[dev-dependencies]
proptest = "1"
use proptest::prelude::*;

fn sort_and_dedup(mut v: Vec<i32>) -> Vec<i32> {
    v.sort();
    v.dedup();
    v
}

proptest! {
    #[test]
    fn sorted_output_is_actually_sorted(v in prop::collection::vec(any::<i32>(), 0..100)) {
        let result = sort_and_dedup(v);
        for window in result.windows(2) {
            prop_assert!(window[0] <= window[1]);
        }
    }

    #[test]
    fn dedup_removes_consecutive_duplicates(v in prop::collection::vec(any::<i32>(), 0..100)) {
        let result = sort_and_dedup(v);
        for window in result.windows(2) {
            prop_assert_ne!(window[0], window[1]);
        }
    }
}

Async Tests with tokio

[dev-dependencies]
tokio = { version = "1", features = ["full", "test-util"] }
#[tokio::test]
async fn fetches_data_successfully() {
    let client = HttpClient::new();
    let response = client.get("https://httpbin.org/json").await.unwrap();
    assert_eq!(response.status(), 200);
}

// Control time in tests
#[tokio::test]
async fn timeout_fires_after_delay() {
    tokio::time::pause();
    let result = tokio::time::timeout(
        std::time::Duration::from_secs(1),
        async {
            tokio::time::sleep(std::time::Duration::from_secs(10)).await;
        },
    ).await;
    tokio::time::advance(std::time::Duration::from_secs(2)).await;
    assert!(result.is_err());
}

Test Fixtures and Cleanup Guards

struct TestDb { path: std::path::PathBuf }

impl TestDb {
    fn new() -> Self {
        let path = std::env::temp_dir().join(format!("test_{}.db", rand_suffix()));
        Self { path }
    }
}

impl Drop for TestDb {
    fn drop(&mut self) {
        let _ = std::fs::remove_file(&self.path);
    }
}

#[test]
fn database_stores_users() {
    let db = TestDb::new();
    // cleanup automatic on drop
}

Benchmarks with Criterion

[dev-dependencies]
criterion = { version = "0.5", features = ["html_reports"] }

[[bench]]
name = "my_benchmark"
harness = false
// benches/my_benchmark.rs
use criterion::{black_box, criterion_group, criterion_main, Criterion, BenchmarkId};

fn bench_fibonacci(c: &mut Criterion) {
    let mut group = c.benchmark_group("fibonacci");
    for i in [10u64, 20, 30].iter() {
        group.bench_with_input(BenchmarkId::from_parameter(i), i, |b, &i| {
            b.iter(|| fibonacci(black_box(i)));
        });
    }
    group.finish();
}

criterion_group!(benches, bench_fibonacci);
criterion_main!(benches);

Common Anti-Patterns

  • Testing private implementation details — test through the public API
  • Sharing mutable state across parallel tests — use #[serial_test] crate or redesign
  • Using real network/filesystem without isolation — use tempfile crate or mock traits
  • unwrap() in tests without context — prefer expect("why this should succeed")
  • Non-deterministic test order dependence — each test must be fully independent

What ships with it

Read from the repository

Just SKILL.md. No reference files, no scripts.

Keep looking

Skills are one crate of 326,758. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.