Rust 测试
单元测试、集成测试与文档测试分工;断言、组织方式与 cargo test 过滤。
#concept
#growing
#dev
#rust
[!info] related notes
Rust 测试
这个概念为什么出现
类型系统抓不完逻辑错误。
Rust 内置测试框架风格:#[test] + cargo test,鼓励与代码同仓。
[!abstract] 一句话理解 单元测试靠近实现(常
#[cfg(test)] mod tests),集成测试走公共 API(tests/),用assert!/assert_eq!验证,由cargo test运行。
最小可运行示例
场景:折扣函数的表驱动单元测试
// 业务意图:验证满 3 件进入批量优惠规则;数量是否合法由调用边界校验。
// 教学点:#[test];assert_eq;cfg(test) 模块。
fn has_bulk_discount(qty: u32) -> bool {
qty >= 3
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn discount_threshold_cases() {
for (qty, expected) in [(0, false), (2, false), (3, true), (4, true)] {
assert_eq!(has_bulk_discount(qty), expected, "qty={qty}");
}
}
}
fn main() {
println!("run cargo test");
}
建议运行:cargo test
期望:一个测试执行四组输入并通过。这里聚焦阈值行为;完整金额、舍入与溢出处理见 函数示例,不在测试入门中重复一套计价实现。
结合场景再看三个关注点
- 测试不进发布二进制(cfg)
- 命名描述行为
- 失败断言打印左右值
核心概念与准确模型
| 类型 | 位置 | 可见性 |
|---|---|---|
| 单元 | 源文件内 | 可测私有项 |
| 集成 | tests/*.rs | 仅公共 API |
| 文档 | 注释代码块 | 公共示例 |
#[should_panic] 只要求测试 panic,必要时加 expected 并缩小被测范围,避免无关 panic 造成假通过。返回 Result 的测试用 Ok 表示通过、Err 表示失败,不与 should_panic 混用。
cargo test name_filter 按名字子串过滤;测试默认可能并行,-- --test-threads=1 可顺序运行,但不能替代资源隔离。CI 应核对测试数量、ignored 项与 feature/target 范围。
设计动机
- 工具链内建,无额外框架门槛
- 文档示例可执行
- 与并发/错误风格一致
边界与误区
- 单测过多测实现细节脆
- 忽略失败路径
- 并行测试下的共享全局状态
[!warning] 常见误区:只用手动 main 验证 自动化回归才是工程。
工程实践
- 纯函数优先单测
- 关键路径集成测
- CI 默认
cargo test - 用测试夹具/临时目录测 I/O
本节总结
- #[test] + cargo test
- 单元/集成分层
- 断言行为而非实现琐碎
自测题
- 集成测试为何测不到私有函数?
- 如何只跑名字含 discount 的测试?
参考答案
- 它们是外部 crate 用户视角。
cargo test discount。
延伸阅读与资料来源
| 资料 | 类型 | 支撑内容 |
|---|---|---|
| The Book — Testing | 官方书 | 测试 |
| Cargo Book — cargo test | 官方 | 命令 |