编写自动化测试
在1972年的文章《谦逊的程序员》中,Edsger W. Dijkstra 提到:“程序测试可以非常有效地展示 bug 的存在,但它却无法证明 bug 的不存在。” 这并不意味着我们不应该尽可能多地进行测试!
我们程序的正确性是指代码按照我们的意图执行的程度。Rust 在设计时非常关注程序的正确性,但正确性是一个复杂的问题,不容易证明。Rust 的类型系统承担了很大一部分责任,但类型系统并不能捕捉到所有问题。因此,Rust 提供了编写自动化软件测试的支持。
假设我们编写了一个函数 add_two
,它将传递给它的数字加 2。这个函数的签名接受一个整数作为参数,并返回一个整数作为结果。当我们实现并编译这个函数时,Rust 会进行所有你到目前为止学到的类型检查和借用检查,以确保我们不会传递一个 String
值或无效的引用给这个函数。但 Rust 无法 检查这个函数是否会完全按照我们的意图执行,即返回参数加 2 而不是参数加 10 或参数减 50!这就是测试发挥作用的地方。
我们可以编写测试来断言,例如,当我们向 add_two
函数传递 3
时,返回的值是 5
。我们可以在每次修改代码时运行这些测试,以确保现有的正确行为没有发生变化。
测试是一项复杂的技能:虽然我们无法在一章中涵盖如何编写良好测试的所有细节,但在本章中,我们将讨论 Rust 测试设施的基本机制。我们将讨论编写测试时可用的注解和宏、运行测试时提供的默认行为和选项,以及如何将测试组织成单元测试和集成测试。