测试策略、错误设计与性能意识
本章目标
这一章学习工程化的三件事:怎么写测试,怎么设计错误,怎么建立性能意识。你会理解为什么“能跑”只是第一步,可靠、可诊断、可扩展才是工程目标。
它是什么
测试是自动验证行为的代码。错误设计是决定失败如何表达和传播。性能意识是知道哪些操作有成本,什么时候需要测量。
Rust 项目中常见测试:
- 单元测试:测试一个函数或模块。
- 集成测试:从外部测试 crate 行为。
- 手动验收:用浏览器或命令行验证完整流程。
为什么需要
没有测试,改文档路由可能破坏博客首页。没有错误设计,读取文件失败可能只显示空白页。没有性能意识,缓存、复制、锁和文件 IO 会在项目变大后成为隐患。
测试不是为了追求数字,而是为了保护关键行为。
怎么使用
一个最小测试:
#[test]
fn escape_html_replaces_angle_brackets() {
let escaped = escape_html("<script>");
assert_eq!(escaped, "<script>");
}
测试函数不接收参数,不返回普通值。失败时通常用 assert! 或 assert_eq! 触发 panic。
逐行解释
#[test]
fn unknown_chapter_returns_404() {
let response = render_docs_response("/docs/not-real").expect("render 404");
assert_eq!(response.status_code, 404);
}
#[test]告诉测试框架这是一个测试函数。- 函数名描述行为:未知章节返回 404。
render_docs_response(...)调用被测函数。.expect("render 404")表示如果函数返回 IO 错误,测试失败并显示提示。assert_eq!比较实际状态码和预期状态码。
这个测试保护一个安全边界:未知路径不应该读取磁盘文件。
常见坑
- 测试只测实现细节会很脆,优先测外部行为。
- 错误信息要让调用者知道失败原因,但不要泄露敏感路径。
- 性能优化前先测量,不要靠感觉。
clone()、文件读取、锁、字符串拼接都可能有成本,但成本是否重要取决于规模。
练习
- 给
percent_decode添加测试。 - 给
normalize_title添加测试,覆盖换行和长度限制。 - 给
/docs/../../Cargo.toml添加 404 测试。 - 用
cargo test运行全部测试。
造轮子任务
写一个迷你测试辅助函数 assert_html_contains(response, text),把重复的响应 body 解码和断言封装起来。目标是体验测试代码也需要良好的 API。
小结
测试、错误和性能是工程可信度的三根支柱。Rust 能在编译期帮你很多,但它不能替你定义业务正确性。你要用测试守住行为,用错误表达失败,用测量指导优化。