Rust 单元测试与基准测试:用 cargo test + criterion 把性能说清楚
test12026-10-022 次阅读
测试是 Rust 的一等公民
Rust 的测试无需额外框架,标准库自带 #[test] 与 assert_eq!。跑 cargo test 即可执行全部测试。当性能敏感时,再用 criterion 做基准测试,量化"改了这段之后到底快了多少"。
第一步:单元与断言
测试和被测试代码放在同一 crate,测试模块用 #[cfg(test)] 标注,发布构建时自动剔除。
// src/parser.rs
pub fn parse_size(s: &str) -> Result<u64, String> {
let (num, unit) = s.split_at(s.len() - 1);
let n: u64 = num.parse().map_err(|_| "数字解析失败".to_string())?;
let mul = match unit {
"K" => 1_000,
"M" => 1_000_000,
_ => return Err("未知单位".to_string()),
};
Ok(n * mul)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn parses_kilobytes() {
assert_eq!(parse_size("3K"), Ok(3_000));
}
#[test]
fn rejects_unknown_unit() {
assert!(parse_size("5X").is_err());
}
#[test]
#[should_panic]
fn panics_on_bad_number() {
// 这里演示 should_panic,实际代码返回 Err 不会 panic
assert_eq!(parse_size("abcK"), Ok(0));
}
}
第二步:基准测试量化热点
criterion 比标准库的 test::Bencher 更稳定,能画出趋势并检测性能回退。在 benches/ 目录下放基准用例。
// benches/parse_bench.rs
use criterion::{black_box, criterion_group, criterion_main, Criterion};
fn bench_parse(c: &mut Criterion) {
c.bench_function("parse_size", |b| {
b.iter(|| {
let _ = black_box(super::parse_size::parse_size("12M"));
});
});
}
criterion_group!(benches, bench_parse);
criterion_main!(benches);
在 Cargo.toml 里声明基准目标,然后 cargo bench 运行:
[dev-dependencies]
criterion = "0.5"
[[bench]]
name = "parse_bench"
harness = false
第三步:用 quickcheck 做属性测试
除了固定用例,还能用属性测试随机生成大量输入,验证"对所有 x 都成立"的不变量。例如解析再拼接应保持一致。
use quickcheck_macros::quickcheck;
#[quickcheck]
fn roundtrip(n: u64) -> bool {
let s = format!("{}K", n);
parse_size(&s) == Ok(n * 1_000)
}
工程要点
- 纯函数优先写单测,副作用(IO、时钟)用 trait 抽象后 mock,测试才稳定。
cargo test --release跑出的结果与 debug 差异很大,基准务必用 release。- criterion 第一次会采样较久,用
cargo bench -- --quick快速验证改动方向。 - 把基准结果按 commit 存下来,CI 里对比,能第一时间发现性能回退而不是上线后才察觉。
T
test1
文章作者
测试是 Rust 的一等公民 Rust 的测试无需额外框架,标准库自带 #[test] 与 assert_eq!。跑...
- 分类
- 技术
- 发布时间
- 2026-10-02
- 字数
- 约 1930 字
- 阅读
- 2 次
