Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

编写自动化测试

Writing Automated Tests

艾兹格·W·迪杰斯特拉(Edsger W. Dijkstra)在他 1972 年的论文《谦卑的程序员》(“The Humble Programmer”)中写道:“程序测试是显示缺陷存在的极有效方式,但对于显示缺陷不存在,它是极度不足的。”这并不意味着我们不应该尽力去进行尽可能多的测试!

In his 1972 essay “The Humble Programmer,” Edsger W. Dijkstra said that “program testing can be a very effective way to show the presence of bugs, but it is hopelessly inadequate for showing their absence.” That doesn’t mean we shouldn’t try to test as much as we can!

程序的“正确性”是指代码在多大程度上实现了我们的意图。Rust 的设计高度关注程序的正确性,但正确性很复杂且不易证明。Rust 的类型系统承担了这一负担的一大部分,但类型系统无法捕获所有问题。因此,Rust 包含了对编写自动化软件测试的支持。

Correctness in our programs is the extent to which our code does what we intend it to do. Rust is designed with a high degree of concern about the correctness of programs, but correctness is complex and not easy to prove. Rust’s type system shoulders a huge part of this burden, but the type system cannot catch everything. As such, Rust includes support for writing automated software tests.

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

Say we write a function add_two that adds 2 to whatever number is passed to it. This function’s signature accepts an integer as a parameter and returns an integer as a result. When we implement and compile that function, Rust does all the type checking and borrow checking that you’ve learned so far to ensure that, for instance, we aren’t passing a String value or an invalid reference to this function. But Rust can’t check that this function will do precisely what we intend, which is return the parameter plus 2 rather than, say, the parameter plus 10 or the parameter minus 50! That’s where tests come in.

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

We can write tests that assert, for example, that when we pass 3 to the add_two function, the returned value is 5. We can run these tests whenever we make changes to our code to make sure any existing correct behavior has not changed.

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

Testing is a complex skill: Although we can’t cover in one chapter every detail about how to write good tests, in this chapter we will discuss the mechanics of Rust’s testing facilities. We’ll talk about the annotations and macros available to you when writing your tests, the default behavior and options provided for running your tests, and how to organize tests into unit tests and integration tests.