Agent skill
rust-async-testing
Comprehensive async/tokio testing patterns for episodic memory operations. Use when writing tests for async functions, time-based operations, concurrent tasks, or tokio runtime management.
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/other/rust-async-testing
SKILL.md
Rust Async Testing Patterns
This skill provides best practices for testing async Rust code with Tokio in the episodic memory system.
Core Patterns
1. Basic Async Test Setup
use tokio::test;
#[tokio::test]
async fn test_episode_creation() {
let memory = SelfLearningMemory::new(Default::default()).await?;
let episode_id = memory.start_episode(
"Test task".to_string(),
TaskContext::default(),
TaskType::CodeGeneration,
).await;
assert!(!episode_id.is_empty());
}
2. Time-Based Testing with Paused Time
For operations involving tokio::time::sleep or timeouts:
#[tokio::test(start_paused = true)]
async fn test_pattern_extraction_timeout() {
let memory = setup_memory().await;
// Time advances only when awaited
let start = tokio::time::Instant::now();
tokio::time::sleep(Duration::from_secs(5)).await;
// Actual elapsed time is near-zero
assert!(start.elapsed().as_millis() < 100);
}
3. Concurrent Operation Testing
#[tokio::test(flavor = "multi_thread", worker_threads = 4)]
async fn test_concurrent_episode_operations() {
let memory = Arc::new(setup_memory().await);
let handles: Vec<_> = (0..10)
.map(|i| {
let memory = memory.clone();
tokio::spawn(async move {
memory.start_episode(
format!("Task {}", i),
TaskContext::default(),
TaskType::CodeGeneration,
).await
})
})
.collect();
let results = futures::future::join_all(handles).await;
assert_eq!(results.len(), 10);
}
4. Storage Backend Mocking
#[tokio::test]
async fn test_episode_with_mock_storage() {
let mock_turso = MockTursoStorage::new();
let mock_redb = MockRedbCache::new();
mock_turso.expect_create_episode()
.times(1)
.returning(|_| Ok(()));
let memory = SelfLearningMemory::with_storage(
mock_turso,
mock_redb,
).await?;
memory.start_episode(/* ... */).await;
}
5. Timeout Testing
#[tokio::test]
async fn test_operation_timeout() {
let result = tokio::time::timeout(
Duration::from_secs(2),
slow_operation()
).await;
assert!(result.is_err(), "Operation should timeout");
}
Memory-Specific Patterns
Episode Lifecycle Testing
#[tokio::test]
async fn test_complete_episode_lifecycle() {
let memory = setup_memory().await;
// 1. Start episode
let episode_id = memory.start_episode(/* ... */).await;
// 2. Log execution steps
memory.log_execution_step(/* ... */).await;
// 3. Complete episode
memory.complete_episode(
episode_id,
TaskOutcome::Success,
None,
).await?;
// 4. Verify storage
let episode = memory.get_episode(&episode_id).await?;
assert_eq!(episode.outcome, TaskOutcome::Success);
}
Pattern Extraction Testing
#[tokio::test]
async fn test_async_pattern_extraction() {
let memory = setup_memory().await;
let episode_id = create_test_episode(&memory).await;
// Pattern extraction runs asynchronously
memory.extract_patterns(episode_id).await?;
// Wait for async workers to complete
tokio::time::sleep(Duration::from_millis(100)).await;
let patterns = memory.get_patterns_for_episode(&episode_id).await?;
assert!(!patterns.is_empty());
}
Best Practices
- Use
#[tokio::test]instead oftokio::test::block_on- cleaner syntax - Enable
start_paused = truefor time-dependent tests - faster execution - Use
flavor = "multi_thread"for concurrency tests - realistic scenarios - Always clean up test data - prevent test pollution
- Mock external dependencies - faster, more reliable tests
- Test error paths - async error handling is critical
Common Pitfalls
- Don't use blocking operations in async tests
// BAD
std::thread::sleep(Duration::from_secs(1));
// GOOD
tokio::time::sleep(Duration::from_secs(1)).await;
- Don't forget to await futures
// BAD - creates future but doesn't run it
memory.start_episode(/* ... */);
// GOOD
memory.start_episode(/* ... */).await;
- Don't use single-threaded runtime for concurrency tests
// BAD - uses single-threaded runtime
#[tokio::test]
async fn test_concurrent_ops() { /* ... */ }
// GOOD
#[tokio::test(flavor = "multi_thread", worker_threads = 4)]
async fn test_concurrent_ops() { /* ... */ }
Resources
- View
resources/tokio-patterns.mdfor advanced patterns - View
resources/concurrent-ops.mdfor parallel execution strategies - View
resources/mock-storage.mdfor storage mocking patterns
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
Didn't find tool you were looking for?