测试
Rust 把测试作为一等公民:标准库提供 #[test] 属性,cargo test 一键运行全部测试。
1. 单元测试
测试与源码同文件、置于 cfg(test) 模块内,保证测试代码不进发布产物:
pub fn add(a: i32, b: i32) -> i32 { a + b }
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_add() {
assert_eq!(add(2, 3), 5);
assert_ne!(add(2, 2), 5);
assert!(add(0, 0) == 0);
}
}ℹ️#[cfg(test)] 的作用
cfg(test) 让这段模块只在 cargo test 时编译。发布构建 cargo build 时它完全不存在,零体积成本。
fn add(a: i32, b: i32) -> i32 { a + b }
fn check(name: &str, pass: bool) {
if pass {
println!("[ok] {}", name);
} else {
println!("[FAIL] {}", name);
}
}
fn main() {
check("add(2,3)==5", add(2, 3) == 5);
check("add(2,2)!=5", add(2, 2) != 5);
println!("测试结束");
}2. 断言宏
| 宏 | 用途 |
|---|---|
assert! | 布尔为真 |
assert_eq!(a, b) | 相等 |
assert_ne!(a, b) | 不等 |
panic! / should_panic | 期望 panic |
#[test]
#[should_panic(expected = "boom")]
fn test_panic() {
panic!("boom");
}fn main() {
let add = |a: i32, b: i32| a + b;
assert_eq!(add(2, 3), 5);
assert_ne!(add(2, 2), 5);
assert!(add(0, 0) == 0);
println!("全部断言通过!");
}3. 集成测试
放在 tests/ 目录,作为独立 crate 调用你的库(只能访问公开 API):
my_lib/
src/lib.rs
tests/
integration.rs // mod tests 不用写,直接写 #[test]
use my_lib::add;
#[test]
fn it_adds() { assert_eq!(add(1, 2), 3); }💡单元测私有,集测测公开
单元测试可测私有函数(同模块 use super::*);集成测试只走公开接口,更像「用户视角」。
4. 运行测试
cargo test # 全部
cargo test add # 按名称过滤
cargo test -- --nocapture # 显示 println! 输出5. 文档测试
写在文档注释里的代码块会被当作测试执行:
/// 两数相加。
/// ```
/// use my_lib::add;
/// assert_eq!(add(2, 2), 4);
/// ```
pub fn add(a: i32, b: i32) -> i32 { a + b }⚠️文档测试要能编译运行
/// 里的 ```rust 代码块会被真的执行。确保它完整可编译,否则 cargo test 报错。不想测可标 ````no_run或ignore`。
🎯练习
给第 8 章的 Rectangle::area 写单元测试:测 0 尺寸、正常尺寸两种情况,并用 cargo test 运行确认全绿。再加一个文档测试示例。
小结
#[test]标记测试;#[cfg(test)]隔离测试代码assert_eq!/assert!/should_panic常用断言- 单元测同文件私有逻辑,集成测试放
tests/测公开 API - 文档注释里的代码块即文档测试
- 下一章看常用派生 trait →