章节目录

测试策略、错误设计与性能意识

本章目标

这一章学习工程化的三件事:怎么写测试,怎么设计错误,怎么建立性能意识。你会理解为什么“能跑”只是第一步,可靠、可诊断、可扩展才是工程目标。

它是什么

测试是自动验证行为的代码。错误设计是决定失败如何表达和传播。性能意识是知道哪些操作有成本,什么时候需要测量。

Rust 项目中常见测试:

  • 单元测试:测试一个函数或模块。
  • 集成测试:从外部测试 crate 行为。
  • 手动验收:用浏览器或命令行验证完整流程。

为什么需要

没有测试,改文档路由可能破坏博客首页。没有错误设计,读取文件失败可能只显示空白页。没有性能意识,缓存、复制、锁和文件 IO 会在项目变大后成为隐患。

测试不是为了追求数字,而是为了保护关键行为。

怎么使用

一个最小测试:

#[test]
fn escape_html_replaces_angle_brackets() {
    let escaped = escape_html("<script>");
    assert_eq!(escaped, "&lt;script&gt;");
}

测试函数不接收参数,不返回普通值。失败时通常用 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()、文件读取、锁、字符串拼接都可能有成本,但成本是否重要取决于规模。

练习

  1. percent_decode 添加测试。
  2. normalize_title 添加测试,覆盖换行和长度限制。
  3. /docs/../../Cargo.toml 添加 404 测试。
  4. cargo test 运行全部测试。

造轮子任务

写一个迷你测试辅助函数 assert_html_contains(response, text),把重复的响应 body 解码和断言封装起来。目标是体验测试代码也需要良好的 API。

小结

测试、错误和性能是工程可信度的三根支柱。Rust 能在编译期帮你很多,但它不能替你定义业务正确性。你要用测试守住行为,用错误表达失败,用测量指导优化。