Skip to main content

Agent Skills Framework Extension

Rust QA Patterns Skill

When to Use This Skill

Use this skill when implementing rust qa patterns patterns in your codebase.

How to Use This Skill

  1. Review the patterns and examples below
  2. Apply the relevant patterns to your implementation
  3. Follow the best practices outlined in this skill

Production Rust testing, code review, safety audits, and quality assurance.

Core Capabilities

  1. Test Strategies - Unit, integration, end-to-end testing
  2. Property Testing - Proptest, quickcheck, generative testing
  3. Safety Audits - Miri, unsafe code review, memory safety
  4. Performance Testing - Criterion benchmarks, profiling
  5. Code Quality - Clippy lints, rustfmt, code review

Comprehensive Testing

// tests/integration_tests.rs
#[cfg(test)]
mod tests {
use super::*;
use sqlx::PgPool;
use testcontainers::{clients::Cli, images::postgres::Postgres, Docker};

// Integration test with real database
#[tokio::test]
async fn test_user_creation_flow() {
let docker = Cli::default();
let postgres = Postgres::default();
let node = docker.run(postgres);

let connection_string = format!(
"postgres://postgres:postgres@127.0.0.1:{}/postgres",
node.get_host_port_ipv4(5432)
);

let pool = PgPool::connect(&connection_string).await.unwrap();

sqlx::migrate!("./migrations")
.run(&pool)
.await
.unwrap();

let repo = UserRepository::new(Arc::new(pool));

// Test creation
let user = CreateUserRequest {
email: "test@example.com".to_string(),
name: "Test User".to_string(),
};

let created = repo.create(user).await.unwrap();
assert_eq!(created.email, "test@example.com");

// Test retrieval
let found = repo.find_by_email("test@example.com").await.unwrap();
assert!(found.is_some());

// Test duplicate email
let duplicate = CreateUserRequest {
email: "test@example.com".to_string(),
name: "Another User".to_string(),
};

let result = repo.create(duplicate).await;
assert!(result.is_err());
}

// Async test with tokio
#[tokio::test]
async fn test_concurrent_requests() {
use futures::future::join_all;

let service = create_test_service().await;

let tasks: Vec<_> = (0..100)
.map(|i| {
let service = service.clone();
tokio::spawn(async move {
service.process_request(i).await
})
})
.collect();

let results = join_all(tasks).await;

assert_eq!(results.len(), 100);
assert!(results.iter().all(|r| r.is_ok()));
}
}

Property-Based Testing

// tests/property_tests.rs
use proptest::prelude::*;

proptest! {
#[test]
fn test_email_validation_properties(email in "[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-z]{2,}") {
// Property: All emails matching regex should validate
prop_assert!(validate_email(&email).is_ok());
}

#[test]
fn test_user_id_roundtrip(user_id in any::<u64>()) {
// Property: Encoding and decoding should be lossless
let encoded = encode_user_id(user_id);
let decoded = decode_user_id(&encoded).unwrap();
prop_assert_eq!(user_id, decoded);
}

#[test]
fn test_pagination_invariants(
total_items in 1..1000usize,
page_size in 1..100usize
) {
// Property: All items should appear exactly once across pages
let mut seen = HashSet::new();

let num_pages = (total_items + page_size - 1) / page_size;

for page in 0..num_pages {
let items = paginate(total_items, page, page_size);

for item in items {
prop_assert!(seen.insert(item), "Duplicate item found");
}
}

prop_assert_eq!(seen.len(), total_items);
}

#[test]
fn test_serialization_roundtrip(data in any::<UserData>()) {
// Property: Serialization should be lossless
let json = serde_json::to_string(&data).unwrap();
let deserialized: UserData = serde_json::from_str(&json).unwrap();
prop_assert_eq!(data, deserialized);
}
}

Safety Audit with Miri

// tests/safety_tests.rs
// Run with: cargo miri test

#[test]
fn test_no_undefined_behavior() {
// Miri detects undefined behavior
let mut data = vec![1, 2, 3, 4, 5];

// Safe access
let first = data.first().unwrap();
assert_eq!(*first, 1);

// This would be caught by Miri if unsafe:
// let ptr = data.as_ptr();
// unsafe { *ptr.add(10) } // Out of bounds!
}

#[test]
fn test_concurrent_access() {
use std::sync::Arc;
use std::thread;

let data = Arc::new(vec![1, 2, 3]);

let handles: Vec<_> = (0..10)
.map(|_| {
let data = Arc::clone(&data);
thread::spawn(move || {
let _val = data[0];
})
})
.collect();

for handle in handles {
handle.join().unwrap();
}
}

// Review unsafe code
#[test]
fn test_unsafe_code_correctness() {
unsafe {
// Document invariants and safety requirements
// 1. Pointer must be valid
// 2. Alignment must be correct
// 3. No data races

let data = vec![1, 2, 3];
let ptr = data.as_ptr();

// Safe: within bounds, aligned, no races
let first = *ptr;
assert_eq!(first, 1);
}
}

Benchmark with Criterion

// benches/benchmarks.rs
use criterion::{black_box, criterion_group, criterion_main, Criterion};

fn benchmark_hashing(c: &mut Criterion) {
c.bench_function("hash_user_id", |b| {
b.iter(|| {
let user_id = black_box("user_12345");
hash_user_id(user_id)
});
});

c.bench_function("hash_user_id_fast", |b| {
b.iter(|| {
let user_id = black_box("user_12345");
hash_user_id_optimized(user_id)
});
});
}

fn benchmark_database_operations(c: &mut Criterion) {
let runtime = tokio::runtime::Runtime::new().unwrap();

c.bench_function("insert_user", |b| {
b.to_async(&runtime).iter(|| async {
let pool = setup_test_pool().await;
insert_user(&pool, black_box("test@example.com")).await
});
});
}

criterion_group!(benches, benchmark_hashing, benchmark_database_operations);
criterion_main!(benches);

Clippy Configuration

# .clippy.toml
cognitive-complexity-threshold = 30
too-many-arguments-threshold = 8

# Cargo.toml
[lints.clippy]
pedantic = "warn"
nursery = "warn"
cargo = "warn"

# Allowed lints
module_name_repetitions = "allow"
missing_errors_doc = "allow"

# Denied lints
unwrap_used = "deny"
expect_used = "deny"
panic = "deny"

CI/CD Quality Gates

# .github/workflows/quality.yml
name: Quality Checks

on: [push, pull_request]

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Run tests
run: cargo test --all-features

- name: Run tests with Miri
run: |
rustup component add miri
cargo miri test

- name: Property tests
run: cargo test --release -- --include-ignored proptest

lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Check formatting
run: cargo fmt -- --check

- name: Run Clippy
run: cargo clippy --all-targets --all-features -- -D warnings

- name: Check documentation
run: cargo doc --no-deps --all-features

benchmark:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Run benchmarks
run: cargo bench --no-fail-fast

coverage:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Install tarpaulin
run: cargo install cargo-tarpaulin

- name: Generate coverage
run: cargo tarpaulin --out Xml

- name: Upload to codecov
uses: codecov/codecov-action@v3

Usage Examples

Integration Testing

Apply rust-qa-patterns skill to create integration tests with testcontainers

Property Testing

Apply rust-qa-patterns skill to add proptest property-based tests for core logic

Benchmarking

Apply rust-qa-patterns skill to set up Criterion benchmarks for performance-critical code

Integration Points

  • rust-development-patterns - Code under test
  • error-debugging-patterns - Error analysis
  • cicd-automation-patterns - Automated testing

Success Output

When successful, this skill MUST output:

✅ SKILL COMPLETE: rust-qa-patterns

Completed:
- [x] Test suite implemented (unit, integration, property-based)
- [x] Safety audit completed (Miri validation)
- [x] Performance benchmarks established (Criterion)
- [x] Code quality validated (Clippy, rustfmt)
- [x] CI/CD quality gates configured and passing

Test Results:
- Unit tests: X/X passing
- Integration tests: Y/Y passing
- Property tests: Z/Z passing
- Miri validation: PASSED (no undefined behavior)
- Clippy lints: 0 warnings (or X allowed)
- Code coverage: X% (statements), Y% (branches)
- Benchmark baseline: X ns/iter (saved for regression tracking)

Outputs:
- Test files: tests/**/*.rs
- Benchmark results: target/criterion/
- Coverage report: target/tarpaulin/index.html
- CI/CD pipeline: .github/workflows/quality.yml

Completion Checklist

Before marking this skill as complete, verify:

  • All unit tests pass (cargo test)
  • Integration tests pass with real dependencies (testcontainers if needed)
  • Property-based tests cover critical invariants (proptest/quickcheck)
  • Miri validation completes without undefined behavior errors
  • Clippy lints pass with configured allowed exceptions
  • Code formatted with rustfmt (cargo fmt --check)
  • Benchmarks established with Criterion (baseline saved)
  • Code coverage meets minimum threshold (70%+)
  • CI/CD pipeline configured with all quality gates
  • Unsafe code documented with safety invariants

Failure Indicators

This skill has FAILED if:

  • ❌ Test failures in cargo test
  • ❌ Miri detects undefined behavior or memory safety issues
  • ❌ Clippy warnings not addressed or properly allowed
  • ❌ rustfmt detects formatting violations
  • ❌ Code coverage below 70% threshold
  • ❌ Property tests fail (invariants violated)
  • ❌ Integration tests fail with real dependencies
  • ❌ Benchmarks show performance regression without justification
  • ❌ CI/CD pipeline failing on quality gates
  • ❌ Unsafe code without safety documentation

When NOT to Use

Do NOT use this skill when:

  • Non-Rust codebase (use language-specific QA patterns)
  • Prototyping phase (comprehensive testing premature)
  • Scripts with no unsafe code or complex logic (basic testing sufficient)
  • FFI bindings already tested by C library (focus on binding safety)
  • Performance not critical (skip benchmarking)
  • Legacy Rust code without test infrastructure (use legacy-rust-migration first)
  • Embedded systems with special test requirements (use embedded-testing-patterns)
  • WebAssembly targets requiring browser tests (use wasm-testing-patterns)

Use alternatives:

  • Python testing → testing-strategies skill
  • JavaScript testing → testing-strategies skill
  • Legacy Rust → legacy-rust-migration skill
  • Embedded → embedded-testing-patterns skill
  • WASM → wasm-testing-patterns skill

Anti-Patterns (Avoid)

Anti-PatternProblemSolution
Ignoring Miri warningsUndefined behavior may existAlways run Miri, fix all warnings
Allowing unwrap() in productionPanic on None/ErrUse unwrap_used Clippy deny, handle errors properly
Skipping property testsMiss edge casesUse proptest for critical invariants
No unsafe code documentationSafety invariants unclearDocument all safety requirements with // SAFETY:
Testing only happy pathErrors not validatedTest error cases, panics, edge conditions
Mocking everythingIntegration issues missedBalance unit tests with integration tests
No benchmark baselineCan't detect regressionsSave criterion baselines, track trends
Ignoring Clippy pedanticMiss code quality issuesEnable pedantic, address or allow with reason
Hard-coded test dataBrittle testsUse test fixtures, proptest strategies
No async test timeoutHanging tests in CISet tokio::test timeout, use tokio::time::timeout

Principles

This skill embodies:

  • #2 First Principles - Understand Rust memory safety guarantees before testing
  • #3 Keep It Simple - TDD with clear AAA pattern
  • #4 Separation of Concerns - Unit vs integration vs property tests
  • #5 Eliminate Ambiguity - Miri removes undefined behavior ambiguity
  • #8 No Assumptions - Property tests verify invariants hold for all inputs
  • #9 Quality Over Speed - Comprehensive testing prevents production bugs

Full Standard: CODITECT-STANDARD-AUTOMATION.md