# 编写自动化测试

Edsgar W. Dijkstra（迪杰斯特拉）在他 1972 年的文章 [《谦卑的程序员，The Humble Programmer》](https://www.cs.utexas.edu/users/EWD/transcriptions/EWD03xx/EWD340.html) 中指出：

> 程序测试虽是显示 bug 存在的有效方式，但他完全不足以显示 bug 不存在。program testing can be a very effective way to show the presence of bugs, but it is hopelessly inadequate for showing their absensce.

这并不意味着我们不应该尽可能多地测试！

所谓程序的 *正确性*，是指我们的代码在多大程度上完成了我们想要他完成的事情。Rust 是在高度关注程序的正确性下设计的，但正确度很复杂且不易证明。Rust 的类型系统承担了这一负担的很大一部分，但类型系统并不能捕获所有问题。因此，Rust 提供了对编写自动化软件测试的支持。

假设我们编写了个函数 `add_two`，加 2 到传递给他的任何数字。这个函数的签名接受一个整数作为参数并返回一个整数作为结果。当我们实现并编译该函数时，Rust 会指定咱们迄今为止学过的所有类型检查与借用检查，以确保我们不会传递 `String` 值或无效引用给该函数。但 Rust *无法* 验证该函数是否将精确地执行咱们想要的操作，即返回参数加 2，而不是参数加 10 或参数减 50！ 这就是测试派上用场的地方。

我们可以编写测试，断言比如当我们传递 `3` 给 `add_two` 函数时，返回值为 `5`。每当我们修改代码后，我们都可以运行这些测试，以确保任何现有的正确行为都没有改变。

测试属于一项复杂技能：虽然我们无法在一章中涵盖到怎样编写良好测试的每个细节，但在这一章中我们将讨论 Rust 的测试设施的各种机制。我们将探讨编写测试时可用的注解与宏、为运行测试提供的默认行为与选项，以及怎样组织测试为单元测试和集成测试。


