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