编写自动化测试

在他的1972年论文《谦逊的程序员》中,Edsger W. Dijkstra 说, “程序测试可以是非常有效的方法来显示错误的存在,但对于证明错误的不存在,它是毫无希望的。” 这并不意味着我们不应该尽我们所能去测试!

正确性是指我们的代码在多大程度上实现了我们的意图。Rust 在设计时非常关注程序的正确性,但正确性是复杂的,不易证明。Rust 的类型系统承担了这一重任的很大一部分,但类型系统并不能捕获一切。因此,Rust 包含了编写自动化软件测试的支持。

假设我们编写了一个名为 add_two 的函数,该函数将 2 加到传递给它的任何数字上。此函数的签名接受一个整数作为参数,并返回一个整数作为结果。当我们实现并编译该函数时,Rust 会执行你迄今为止所学的所有类型检查和借用检查,以确保例如我们没有将 String 值或无效引用传递给此函数。但是 Rust 不能 检查此函数是否会精确地执行我们的意图,即返回参数加 2 而不是参数加 10 或参数减 50!这就是测试的作用。

我们可以编写测试,例如,断言当我们传递3add_two函数时,返回的值是5。我们可以在每次对代码进行更改时运行这些测试,以确保任何现有的正确行为没有改变。

测试是一项复杂的技能:虽然我们无法在这一章中涵盖如何编写良好测试的每一个细节,但在本章中我们将讨论 Rust 测试设施的机制。我们将讨论编写测试时可用的注解和宏,运行测试时提供的默认行为和选项,以及如何将测试组织成单元测试和集成测试。