Rust 测试
单元测试、集成测试与文档测试分工;断言、组织方式与 cargo test 过滤。
#type / concept
#status / growing
#tech / dev
#resource / rust
[!info] 关联笔记
Rust 测试
这个概念为什么出现
类型系统抓不完逻辑错误。
Rust 内置测试框架风格:#[test] + cargo test,鼓励与代码同仓。
[!abstract] 一句话理解 单元测试靠近实现(常
#[cfg(test)] mod tests),集成测试走公共 API(tests/),用assert!/assert_eq!验证,由cargo test运行。
最小可运行示例
场景:折扣函数的表驱动单元测试
// 业务意图:验证满 3 件 9 折。
// 教学点:#[test];assert_eq;cfg(test) 模块。
fn discounted_total_cents(unit: i32, qty: i32) -> i32 {
let raw = unit * qty;
if qty >= 3 { raw * 90 / 100 } else { raw }
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn no_discount_below_3() {
assert_eq!(discounted_total_cents(1000, 2), 2000);
}
#[test]
fn discount_at_3() {
assert_eq!(discounted_total_cents(1000, 3), 2700);
}
}
fn main() {
println!("run cargo test");
}
建议运行:cargo test
期望:两个测试通过。
结合场景再看三个关注点
- 测试不进发布二进制(cfg)
- 命名描述行为
- 失败断言打印左右值
核心概念与准确模型
| 类型 | 位置 | 可见性 |
|---|---|---|
| 单元 | 源文件内 | 可测私有项 |
| 集成 | tests/*.rs | 仅公共 API |
| 文档 | 注释代码块 | 公共示例 |
#[should_panic]、Result 返回的测试、cargo test name_filter。
设计动机
- 工具链内建,无额外框架门槛
- 文档示例可执行
- 与并发/错误风格一致
边界与误区
- 单测过多测实现细节脆
- 忽略失败路径
- 并行测试下的共享全局状态
[!warning] 常见误区:只用手动 main 验证 自动化回归才是工程。
工程实践
- 纯函数优先单测
- 关键路径集成测
- CI 默认
cargo test - 用测试夹具/临时目录测 I/O
本节总结
- #[test] + cargo test
- 单元/集成分层
- 断言行为而非实现琐碎
自测题
- 集成测试为何测不到私有函数?
- 如何只跑名字含 discount 的测试?
参考答案
- 它们是外部 crate 用户视角。
cargo test discount。
延伸阅读与资料来源
| 资料 | 类型 | 支撑内容 |
|---|---|---|
| The Book — Testing | 官方书 | 测试 |
| Cargo Book — cargo test | 官方 | 命令 |