Rust Testing Patterns 是一份面向 Rust 语言项目的测试模式指南,目的是帮助开发者写出可靠、可维护的测试,并遵循 TDD(测试驱动开发)方法。资料覆盖单元测试、集成测试、异步测试、基于属性的测试、Mock 以及覆盖率等主题。
用途与适用时机:编写新的 Rust 函数、方法或 trait 时;为已有代码补充测试覆盖时;为性能关键代码创建基准测试时;为输入校验实现属性测试时;在 Rust 项目中实践 TDD 工作流时,都可以使用这套模式。
主要能力与工作方式:整体流程为——定位要测试的函数、trait 或模块;编写测试(在 #[cfg(test)] 模块中使用 #[test],用 rstest 做参数化测试,或用 proptest 做属性测试);使用 mockall 模拟依赖以隔离被测单元;先运行测试确认其以预期错误失败(RED);再编写最小实现使测试通过(GREEN);随后在测试保持通过的前提下重构;最后检查覆盖率,使用 cargo-llvm-cov 并以 80%+ 为目标。
具体测试类型:
- 单元测试:在源码模块内用 #[cfg(test)] mod tests 组织,配合 assert_eq!、assert_ne!、assert! 等断言宏,以及带自定义消息的断言和浮点比较。
- 错误与 panic 测试:既可用返回 Result 的测试配合 ? 运算符验证错误路径,也可用 #[should_panic] 及 expected 参数验证 panic。
- 集成测试:放在 tests/ 目录,每个文件是独立的测试二进制,并可在 common/ 中放置共享工具。
- 异步测试:用 #[tokio::test] 编写异步测试,并可结合 tokio::time::timeout 测试超时。
- 参数化测试与 fixture:用 rstest 的 #[case] 提供多组输入,用 #[fixture] 提供测试夹具。
- 属性测试:用 proptest! 宏定义不变量(如编解码往返、排序保持长度、排序输出有序),并可通过自定义 Strategy 生成合法输入(如邮箱)。
- Mock:用 mockall 的 #[automock] 基于 trait 生成 mock,配合 expect_*、with、times、returning 设定期望行为。
- 文档测试:在文档注释中用可执行示例(含 no_run)作为测试。
- 基准测试:用 Criterion 定义 bench_function,并在 Cargo.toml 中配置 [[bench]] 与 harness = false。
- 覆盖率:cargo llvm-cov 可输出摘要、HTML 或 LCOV,并可用 --fail-under-lines 设定阈值。资料给出的覆盖率目标为:关键业务逻辑 100%,公共 API 90%+,一般代码 80%+,生成代码或 FFI 绑定可排除。
常用命令:cargo test(全部测试)、cargo test -- --nocapture、cargo test test_name、cargo test --lib、cargo test --test api_test、cargo test --doc、cargo test --no-fail-fast、cargo test -- --ignored。
最佳实践:先写测试;用 #[cfg(test)] 模块写单元测试;测试行为而非实现;使用描述性测试名;优先用 assert_eq! 获得更好的错误信息;在返回 Result 的测试中用 ?;保持测试相互独立;能用 Result::is_err() 时不用 #[should_panic];不要什么都 mock;不用 sleep() 而用通道、屏障或 tokio::time::pause();不要跳过错误路径测试;不忽略不稳定的测试。
CI 集成:给出了 GitHub Actions 示例,包含检出代码、安装 stable 工具链(含 clippy、rustfmt 组件)、cargo fmt --check、cargo clippy -- -D warnings、cargo test,以及安装并用 cargo llvm-cov --fail-under-lines 80 检查覆盖率。
限制:资料未提供适用的 Rust 版本、各 crate 的兼容范围、许可证与安装要求等具体信息。