Rust 测试:高质量代码的框架与工具

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

Rust 测试:从单元测试到基于属性的测试



Rust 是少数几种语言之一,其类型系统和所有权机制在编译阶段就能排除整类错误(数据竞争、悬垂指针、双重释放内存)。然而,逻辑错误、边界情况处理不当以及错误的业务逻辑仍然存在。为了发现这些问题,Rust 生态系统形成了一套强大的测试工具集——从内置的测试运行器到用于生成测试数据的高级框架。



内置工具:cargo test



基本的测试工具直接内置于编译器和包管理器中。要创建测试,只需添加一个带有 #[cfg(test)] 属性的模块,并用 #[test] 属性标记函数即可。



// src/lib.rspub fn add(left: u64, right: u64) -> u64 {    left + right}

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

#[test] fn test_add() { let result = add(2, 2); assert_eq!(result, 4); }

#[test] fn test_add_negative() { // u64 不支持负数——这是编译错误 // 但如果函数接受 i64: // assert_eq!(add(-2, 2), 0); }}


运行:cargo test。标志 -- --nocapture 会输出测试中的 println!。标志 -- --test-threads=1 会禁用并行运行。



集成测试



集成测试位于项目根目录的 tests/ 文件夹中。每个文件都是一个独立的 crate,可以测试库的公共 API。



// tests/integration_test.rsuse my_library::add;

#[test]fn test_integration() { assert_eq!(add(10, 20), 30);}


对于测试二进制 crate(带有 main.rs),可以使用 assert_cmd——它将二进制文件作为外部进程运行并检查 stdout/stderr。



基于属性的测试:proptest 和 quickcheck



与其手动编写数十个测试用例,基于属性的测试会生成数千个随机输入数据并检查不变量。两个主要框架:



  • proptest——现代、灵活,支持策略、过滤和示例缩减(shrink)。
  • quickcheck——较老,受 Haskell QuickCheck 启发,更简单但功能较弱。


使用 proptest 的示例:



use proptest::prelude::*;

fn reverse_string(s: &str) -> String { s.chars().rev().collect()}

proptest! { #[test] fn test_reverse_twice(s in ".*") { let reversed = reverse_string(&s); let double_reversed = reverse_string(&reversed); assert_eq!(s, double_reversed); }

#[test] fn test_reverse_length(s in ".*") { let reversed = reverse_string(&s); assert_eq!(s.len(), reversed.len()); }}


如果测试失败,proptest 会找到最小的反例(shrinking)。



测试异步代码:tokio-test



对于使用 tokio 的异步函数,普通测试不适用——需要一个异步运行时。tokio-test 提供了 #[tokio::test] 宏。



use tokio::time::{sleep, Duration};

async fn delayed_add(a: u32, b: u32) -> u32 { sleep(Duration::from_millis(10)).await; a + b}

#[tokio::test]async fn test_delayed_add() { let result = delayed_add(3, 5).await; assert_eq!(result, 8);}


也可以使用 futures-test 来处理 futures 和 async-std。



模拟和桩:mockall 和 mockito



为了将测试与外部依赖(数据库、API、文件系统)隔离开来,

推荐