Skip to content

完整示例

被测试的代码

rust
// src/lib.rs

/// 计算斐波那契数列
pub fn fibonacci(n: u32) -> u64 {
    match n {
        0 => 0,
        1 => 1,
        _ => {
            let mut a = 0;
            let mut b = 1;
            for _ in 2..=n {
                let temp = a + b;
                a = b;
                b = temp;
            }
            b
        }
    }
}

/// 计算最大值
pub fn max<T: Ord>(a: T, b: T) -> T {
    if a > b { a } else { b }
}

/// 用户结构体
pub struct User {
    pub name: String,
    pub age: u32,
}

impl User {
    pub fn new(name: String, age: u32) -> Self {
        User { name, age }
    }

    pub fn name(&self) -> &str {
        &self.name
    }

    pub fn is_adult(&self) -> bool {
        self.age >= 18
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_fibonacci() {
        assert_eq!(fibonacci(0), 0);
        assert_eq!(fibonacci(1), 1);
        assert_eq!(fibonacci(5), 5);
        assert_eq!(fibonacci(10), 55);
    }

    #[test]
    fn test_max() {
        assert_eq!(max(1, 2), 2);
        assert_eq!(max("a", "b"), "b");
    }

    #[test]
    fn test_user_is_adult() {
        let user = User::new(String::from("Alice"), 20);
        assert!(user.is_adult());

        let minor = User::new(String::from("Bob"), 15);
        assert!(!minor.is_adult());
    }
}
▶ Run

集成测试

rust
// tests/integration_test.rs
use my_crate::{User, fibonacci};

#[test]
fn test_fibonacci_sequence() {
    let expected = [0, 1, 1, 2, 3, 5, 8, 13, 21, 34];
    for (i, &exp) in expected.iter().enumerate() {
        assert_eq!(fibonacci(i as u32), exp);
    }
}

#[test]
fn test_user_creation() {
    let user = User::new(String::from("Charlie"), 30);
    assert_eq!(user.name(), "Charlie");
    assert!(user.is_adult());
}
▶ Run

测试最佳实践

测试命名

rust
#[test]
fn test_add_positive_numbers() {}

#[test]
fn test_add_negative_numbers() {}

#[test]
fn test_add_mixed_numbers() {}

// 或使用描述性名称(推荐)
#[test]
fn add_returns_sum_of_two_numbers() {}

#[test]
fn add_zero_to_number_returns_number() {}

#[test]
fn add_negative_numbers_returns_correct_sum() {}
▶ Run

AAA 模式

rust
#[test]
fn test_user_discount() {
    // Arrange(准备)
    let user = User::new(String::from("Alice"), 25);
    let cart = Cart::new();
    cart.add_item(Item::new("Book", 20.0));

    // Act(执行)
    let total = cart.calculate_total(&user);

    // Assert(断言)
    assert_eq!(total, 18.0);  // 10% 折扣
}
▶ Run

测试夹具

rust
#[cfg(test)]
mod tests {
    use super::*;

    // 测试夹具
    struct TestFixture {
        user: User,
        cart: Cart,
    }

    impl TestFixture {
        fn new() -> Self {
            TestFixture {
                user: User::new(String::from("Test"), 25),
                cart: Cart::new(),
            }
        }
    }

    impl Drop for TestFixture {
        fn drop(&mut self) {
            // 清理资源
        }
    }

    #[test]
    fn test_checkout() {
        let mut fixture = TestFixture::new();
        fixture.cart.add_item(Item::new("Book", 20.0));

        let total = fixture.cart.calculate_total(&fixture.user);
        assert_eq!(total, 18.0);
    }
}
▶ Run

常见错误

错误 1:忘记 #[cfg(test)]

rust
// ❌ 错误:测试代码会被编译到生产代码
mod tests {
    // ...
}

// ✅ 正确
#[cfg(test)]
mod tests {
    // ...
}
▶ Run

错误 2:测试依赖外部状态

rust
// ❌ 不好
#[test]
fn test_with_global_state() {
    // 依赖全局变量或时间
}

// ✅ 好
#[test]
fn test_isolated() {
    // 自包含的测试,不依赖外部状态
}
▶ Run

错误 3:测试过于复杂

rust
// ❌ 不好
#[test]
fn test_everything() {
    // 100 行测试代码,测试多个功能
}

// ✅ 好
#[test]
fn test_single_feature() {
    // 只测试一个功能
}
▶ Run

练习

练习 1:单元测试

为你的项目编写单元测试,覆盖所有公共函数。

练习 2:集成测试

创建集成测试验证模块间交互。

练习 3:文档测试

为公共 API 编写文档测试。

小结

本章我们学习了:

  • ✅ 单元测试
  • ✅ 集成测试
  • ✅ 文档测试
  • ✅ 断言宏
  • ✅ 基准测试
  • ✅ 生成文档
  • ✅ 测试覆盖率

测试命令速查

命令说明
cargo test运行所有测试
cargo test test_name运行特定测试
cargo test -- --nocapture显示输出
cargo test --doc只运行文档测试
cargo doc --open生成并打开文档
cargo llvm-cov生成覆盖率报告
cargo bench运行基准测试

测试金字塔

         /\
        /  \
       / E2E\      端到端测试(少量)
      /______\
     /        \
    /Integration\  集成测试(适量)
   /______________\
  /    Unit Tests   \  单元测试(大量)
 /____________________\

测试建议

  1. 多写单元测试 - 快速、隔离、易维护
  2. 适量集成测试 - 验证模块间交互
  3. 文档测试 - 保证示例代码正确
  4. 避免过度测试 - 测试实现细节会降低重构能力

教程完成!祝你 Rust 学习愉快!