Rust Testing Skill
When to Activate
Activate this skill when:
-
Writing Rust unit tests
-
Creating integration tests
-
Working with doc tests
-
Setting up property-based testing
-
Running benchmarks
Quick Commands
Run all tests
cargo test
With output
cargo test -- --nocapture
Run specific test
cargo test test_user_create
Run tests in module
cargo test auth::
Run ignored tests
cargo test -- --ignored
Doc tests only
cargo test --doc
Integration tests only
cargo test --test integration
Unit Tests (Same File)
pub fn add(a: i32, b: i32) -> i32 { a + b }
#[cfg(test)] mod tests { use super::*;
#[test]
fn test_add() {
assert_eq!(add(2, 3), 5);
}
#[test]
fn test_add_negative() {
assert_eq!(add(-1, -1), -2);
}
}
Test Attributes
#[test] fn regular_test() { }
#[test] #[ignore] fn slow_test() { } // Skip unless --ignored
#[test] #[should_panic] fn test_panic() { panic!("This should panic"); }
#[test] #[should_panic(expected = "specific message")] fn test_panic_message() { panic!("specific message here"); }
#[test] fn test_with_result() -> Result<(), String> { let result = some_operation()?; assert_eq!(result, expected); Ok(()) }
Assertions
// Basic assert_eq!(1 + 1, 2); assert_ne!(1 + 1, 3); assert!(true);
// With messages assert_eq!(result, expected, "values should match: got {}", result);
// Pattern matching assert!(matches!(value, Pattern::Variant(_)));
// Option/Result assert!(some_option.is_some()); assert!(some_result.is_ok());
Integration Tests
// tests/api_integration.rs use my_crate::{Config, Server};
#[test] fn test_server_startup() { let config = Config::default(); let server = Server::new(config); assert!(server.start().is_ok()); }
Directory Structure
project/ ├── Cargo.toml ├── src/ │ ├── lib.rs # Unit tests in #[cfg(test)] │ └── user.rs # Module with inline tests └── tests/ # Integration tests ├── common/ │ └── mod.rs # Shared utilities └── api_test.rs
Mocking with Traits
pub trait UserRepository { fn find_by_id(&self, id: u64) -> Option<User>; }
#[cfg(test)] mod tests { use super::*; use std::collections::HashMap;
struct MockUserRepo {
users: HashMap<u64, User>,
}
impl UserRepository for MockUserRepo {
fn find_by_id(&self, id: u64) -> Option<User> {
self.users.get(&id).cloned()
}
}
#[test]
fn test_user_service() {
let mut users = HashMap::new();
users.insert(1, User { id: 1, email: "test@example.com".into() });
let repo = MockUserRepo { users };
let service = UserService::new(Box::new(repo));
let user = service.get_user(1).unwrap();
assert_eq!(user.email, "test@example.com");
}
}
Async Testing (tokio)
#[tokio::test] async fn test_async_operation() { let result = fetch_data().await; assert!(result.is_ok()); }
#[tokio::test] async fn test_with_timeout() { let result = tokio::time::timeout( Duration::from_secs(5), slow_operation() ).await; assert!(result.is_ok()); }
Doc Tests
/// Adds two numbers together.
///
/// # Examples
///
/// /// use my_crate::add; /// let result = add(2, 3); /// assert_eq!(result, 5); ///
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
Property-Based Testing (proptest)
use proptest::prelude::*;
proptest! { #[test] fn test_add_commutative(a: i32, b: i32) { prop_assert_eq!(add(a, b), add(b, a)); } }
Coverage
Using cargo-tarpaulin
cargo install cargo-tarpaulin cargo tarpaulin --out Html
Using cargo-llvm-cov
cargo install cargo-llvm-cov cargo llvm-cov --html
Related Resources
See AgentUsage/testing_rust.md for complete documentation including:
-
Benchmarking with criterion
-
Setup/teardown patterns
-
Mockall crate usage
-
CI configuration