rust-testing-advanced
Advanced Rust testing anti-patterns and corrections — cfg(test) placement, expect() over unwrap(), mockall expectation ordering, executor mixing (#[tokio::test] vs block_on), PgPool isolation with
Best use case
rust-testing-advanced is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Advanced Rust testing anti-patterns and corrections — cfg(test) placement, expect() over unwrap(), mockall expectation ordering, executor mixing (#[tokio::test] vs block_on), PgPool isolation with
Teams using rust-testing-advanced should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/rust-testing-advanced/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How rust-testing-advanced Compares
| Feature / Agent | rust-testing-advanced | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Advanced Rust testing anti-patterns and corrections — cfg(test) placement, expect() over unwrap(), mockall expectation ordering, executor mixing (#[tokio::test] vs block_on), PgPool isolation with
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# Rust Testing — Advanced Patterns
This skill extends `rust-testing` with anti-patterns and corrections. Load `rust-testing` first.
## When to Activate
- Reviewing Rust test code for common mistakes
- Debugging flaky tests caused by shared pool state
- Diagnosing mock setup ordering errors (already-moved mock)
- Fixing async test executor mismatches
- Reducing release binary size from mis-placed test code
---
## Anti-Patterns
### Placing Tests Outside #[cfg(test)] in Source Files
**Wrong:**
```rust
// src/domain/discount.rs
pub fn apply_discount(price: f64, tier: CustomerTier) -> f64 { /* ... */ }
#[test] // Compiles into release builds — wastes binary size
fn standard_no_discount() {
assert_eq!(apply_discount(100.0, CustomerTier::Standard), 100.0);
}
```
**Correct:**
```rust
pub fn apply_discount(price: f64, tier: CustomerTier) -> f64 { /* ... */ }
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn standard_no_discount() {
assert_eq!(apply_discount(100.0, CustomerTier::Standard), 100.0);
}
}
```
**Why:** Without `#[cfg(test)]`, test code and its dependencies are compiled into release binaries, increasing binary size and compile time.
### Using unwrap() in Tests Instead of Descriptive Assertions
**Wrong:**
```rust
#[test]
fn save_user() {
let user = repo.save(&new_user()).await.unwrap(); // Panic message is useless
assert_eq!(user.email, "alice@test.com");
}
```
**Correct:**
```rust
#[test]
async fn save_user() {
let user = repo.save(&new_user()).await
.expect("saving a valid user should not fail");
assert_eq!(user.email, "alice@test.com");
}
```
**Why:** `expect("context")` produces a meaningful panic message that explains what went wrong at the test boundary, making failures far easier to diagnose.
### Setting Up Mock Expectations After Creating the Service
**Wrong:**
```rust
let service = UserService::new(Arc::new(mock)); // mock moved in
mock.expect_save().returning(|_| Ok(saved_user())); // compile error: already moved
```
**Correct:**
```rust
let mut mock = MockUserRepository::new();
mock.expect_save()
.times(1)
.returning(|_| Ok(saved_user()));
let service = UserService::new(Arc::new(mock)); // move after setup
```
**Why:** Expectations must be configured before the mock is moved into the service under test; setting them up first also makes the test intent readable at a glance.
### Running Async Tests with std::thread::block_on Instead of #[tokio::test]
**Wrong:**
```rust
#[test]
fn fetch_returns_user() {
let result = futures::executor::block_on(service.fetch(1)); // Wrong executor
assert!(result.is_ok());
}
```
**Correct:**
```rust
#[tokio::test]
async fn fetch_returns_user() {
let result = service.fetch(1).await;
assert!(result.is_ok());
}
```
**Why:** Mixing executors causes panics or silent hangs; `#[tokio::test]` provides a proper single-threaded Tokio runtime that matches the runtime used in production.
### Sharing a Single PgPool Across All Integration Tests
**Wrong:**
```rust
// tests/common/mod.rs
static POOL: Lazy<PgPool> = Lazy::new(|| { /* ... */ });
// Tests share state — inserts from one test pollute another
```
**Correct:**
```rust
#[sqlx::test] // sqlx::test injects a fresh, isolated pool per test
async fn find_by_id_returns_none(pool: PgPool) {
let repo = PostgresUserRepo::new(pool);
assert!(repo.find_by_id(9999).await.unwrap().is_none());
}
```
**Why:** `#[sqlx::test]` wraps each test in its own transaction that is rolled back after the test, guaranteeing isolation without manual cleanup.
## Reference
- `rust-testing` — core testing patterns (unit, mocks, integration, benchmarks, CI)Related Skills
zero-trust-patterns
Zero-Trust security patterns — mTLS between microservices (Istio/SPIFFE), SPIRE workload identity, OPA/Envoy authorization, NetworkPolicy default-deny-all, short-lived credentials, service mesh security, and Kubernetes RBAC hardening.
visual-testing
Visual Regression Testing: tool comparison (Chromatic/Percy/Playwright screenshots/BackstopJS), pixel-diff vs AI-based comparison, baseline management, flakiness strategies (masks, tolerances, waitForLoadState), CI integration with GitHub Actions, and Storybook integration.
typescript-testing
TypeScript testing patterns: Vitest for unit/integration, Playwright for E2E, MSW for API mocking, Testing Library for React components. Core TDD methodology for TypeScript/JavaScript projects.
typescript-patterns-advanced
Advanced TypeScript — mapped types, template literal types, conditional types, infer, type guards, decorators, async patterns, testing with Vitest/Jest, and performance. Extends typescript-patterns.
tdd-workflow-advanced
TDD anti-patterns — writing code before tests, testing implementation details instead of behavior, using waitForTimeout as a sync strategy, chaining tests that share state, mocking the system under test instead of its dependencies.
swift-testing
Swift testing patterns: Swift Testing framework (Swift 6+), XCTest for UI tests, async/await test cases, actor testing, Combine testing, and XCUITest for UI automation. TDD for Swift/SwiftUI.
swift-protocol-di-testing
Protocol-based dependency injection for testable Swift code — mock file system, network, and external APIs using focused protocols and Swift Testing.
swift-patterns-advanced
Advanced Swift patterns — property wrappers, result builders, Combine basics, opaque & existential types, macro system, advanced generics, and performance optimization. Extends swift-patterns.
serverless-patterns-advanced
Advanced Serverless patterns — Lambda idempotency (Lambda Powertools + DynamoDB persistence layer), Lambda cost model (pricing formula, break-even vs containers), and CloudWatch Insights observability queries for cold starts, duration, and errors.
security-review-advanced
Security anti-patterns — localStorage token storage (XSS risk), trusting client-side authorization checks, reflecting full error details to clients, blacklist vs whitelist input validation, using npm install instead of npm ci in CI pipelines.
scala-testing
Scala testing with ScalaTest, MUnit, and ScalaCheck: FunSpec/FlatSpec test structure, property-based testing with forAll, mocking with MockitoSugar, Cats Effect testing with munit-cats-effect (runTest/IOSuite), ZIO Test, Testcontainers-Scala for database integration tests, and CI integration with sbt. Use when writing or reviewing Scala tests.
rust-web-patterns
Axum HTTP handlers, Serde serialization, async channels, iterator patterns, trait objects, configuration, and WebAssembly target for Rust web services.