编写自动化测试

在 1972 年的论文《谦虚的程序员》中,Edsger W. Dijkstra 说:“程序测试可以非常有效地显示 bug 的存在,但它对于显示 bug 的不存在是完全不够的。” 这并不意味着我们不应该尽可能地尝试测试!

程序中的正确性是指我们的代码在多大程度上执行我们想要它执行的操作。Rust 的设计高度关注程序的正确性,但正确性是复杂的,并且不容易证明。Rust 的类型系统承担了这方面的大部分负担,但类型系统无法捕获所有内容。因此,Rust 包含了对编写自动化软件测试的支持。

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

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

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