rust-async-testing

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Rust Async Testing Patterns

Rust 异步测试模式

Best practices for testing async Rust code with Tokio.
使用Tokio测试Rust异步代码的最佳实践。

Core Patterns

核心模式

Basic Async Test

基础异步测试

rust
#[tokio::test]
async fn test_episode_creation() {
    let memory = SelfLearningMemory::new(Default::default()).await?;
    let id = memory.start_episode("Test", ctx, TaskType::CodeGen).await;
    assert!(!id.is_empty());
}
rust
#[tokio::test]
async fn test_episode_creation() {
    let memory = SelfLearningMemory::new(Default::default()).await?;
    let id = memory.start_episode("Test", ctx, TaskType::CodeGen).await;
    assert!(!id.is_empty());
}

Time-Based Testing

基于时间的测试

rust
#[tokio::test(start_paused = true)]
async fn test_timeout_behavior() {
    // Time advances only when awaited
    let start = tokio::time::Instant::now();
    tokio::time::sleep(Duration::from_secs(5)).await;
    assert!(start.elapsed().as_millis() < 100);
}
rust
#[tokio::test(start_paused = true)]
async fn test_timeout_behavior() {
    // Time advances only when awaited
    let start = tokio::time::Instant::now();
    tokio::time::sleep(Duration::from_secs(5)).await;
    assert!(start.elapsed().as_millis() < 100);
}

Concurrent Operations

并发操作测试

rust
#[tokio::test(flavor = "multi_thread", worker_threads = 4)]
async fn test_concurrent_episodes() {
    let memory = Arc::new(setup_memory().await);

    let handles: Vec<_> = (0..10).map(|i| {
        let mem = memory.clone();
        tokio::spawn(async move {
            mem.start_episode(format!("Task {}", i), ctx, type_).await
        })
    }).collect();

    let results = futures::future::join_all(handles).await;
    assert_eq!(results.len(), 10);
}
rust
#[tokio::test(flavor = "multi_thread", worker_threads = 4)]
async fn test_concurrent_episodes() {
    let memory = Arc::new(setup_memory().await);

    let handles: Vec<_> = (0..10).map(|i| {
        let mem = memory.clone();
        tokio::spawn(async move {
            mem.start_episode(format!("Task {}", i), ctx, type_).await
        })
    }).collect();

    let results = futures::future::join_all(handles).await;
    assert_eq!(results.len(), 10);
}

Timeout Testing

超时测试

rust
#[tokio::test]
async fn test_operation_timeout() {
    let result = tokio::time::timeout(
        Duration::from_secs(2),
        slow_operation()
    ).await;
    assert!(result.is_err());
}
rust
#[tokio::test]
async fn test_operation_timeout() {
    let result = tokio::time::timeout(
        Duration::from_secs(2),
        slow_operation()
    ).await;
    assert!(result.is_err());
}

Best Practices

最佳实践

  1. Use
    #[tokio::test]
    instead of
    block_on
  2. Enable
    start_paused = true
    for time tests
  3. Use
    multi_thread
    for concurrency tests
  4. Mock external dependencies
  5. Test error paths
  1. 使用
    #[tokio::test]
    替代
    block_on
  2. 针对时间测试启用
    start_paused = true
  3. 针对并发测试使用
    multi_thread
    运行时
  4. 模拟外部依赖
  5. 测试错误路径

Common Pitfalls

常见误区

BadGood
std::thread::sleep()
tokio::time::sleep().await
memory.start_episode()
memory.start_episode().await
Single-threaded for concurrency
multi_thread
runtime
错误做法正确做法
std::thread::sleep()
tokio::time::sleep().await
memory.start_episode()
memory.start_episode().await
单线程运行并发测试
multi_thread
运行时

Memory-Specific Pattern

针对记忆模块的特定模式

rust
#[tokio::test]
async fn test_complete_lifecycle() {
    let memory = setup_memory().await;

    // Start → Log Steps → Complete → Verify
    let id = memory.start_episode("test", ctx, type_).await;
    memory.log_execution_step(id.clone(), step).await;
    memory.complete_episode(id.clone(), outcome, None).await?;

    let episode = memory.get_episode(&id).await?;
    assert_eq!(episode.outcome, outcome);
}
rust
#[tokio::test]
async fn test_complete_lifecycle() {
    let memory = setup_memory().await;

    // Start → Log Steps → Complete → Verify
    let id = memory.start_episode("test", ctx, type_).await;
    memory.log_execution_step(id.clone(), step).await;
    memory.complete_episode(id.clone(), outcome, None).await?;

    let episode = memory.get_episode(&id).await?;
    assert_eq!(episode.outcome, outcome);
}