mirror of
https://github.com/gnu4cn/rust-lang-zh_CN.git
synced 2026-08-19 12:43:28 +08:00
Updated 'src/Ch11_Writing_Automated_Tests.md'.
This commit is contained in:
@@ -1,13 +1,17 @@
|
||||
# 编写自动化测试
|
||||
|
||||
在 Edsgar W. Dijkstra(迪杰斯特拉) 1972 年论文 [《谦卑的程序员(The Humble Programmer)》](https://www.cs.utexas.edu/users/EWD/transcriptions/EWD03xx/EWD340.html)中,迪杰斯特拉指出 “程序测试可以是一种揭示代码存在的非常有效方式,但对于揭示代码错误存在,程序测试又显得不那么足够(Program testing can be a very effective way to show the presence of bugs, but it is hopelessly inadequate for showing their absensce)。” 这并不意味着咱们就不要尽力进行尽可能多的测试!
|
||||
Edsgar W. Dijkstra(迪杰斯特拉)在他 1972 年的文章 [《谦卑的程序员,The Humble Programmer》](https://www.cs.utexas.edu/users/EWD/transcriptions/EWD03xx/EWD340.html) 中指出:
|
||||
|
||||
所谓计算机程序正确,即为所编写代码,在多大程度上完成了想要他完成的事情。Rust 是以高度关注程序正确度而设计的,不过正确度是个复杂的问题,而不易于证明。Rust 的类型系统承担了保证正确性的很大部分,但类型系统并不能捕获到所有东西。由于这方面的原因,Rust 包括了编写自动化软件测试的支持。
|
||||
> 程序测试虽是显示 bug 存在的有效方式,但他完全不足以显示 bug 不存在。program testing can be a very effective way to show the presence of bugs, but it is hopelessly inadequate for showing their absensce.
|
||||
|
||||
这里假设说编写了一个将 `2` 加到所传入任何数字的一个函数 `add_two`。该函数的签名,会接受某个整数作为参数,并返回一个整数作为计算结果。在实现并编译那个函数时,Rust 会完成至此所掌握的全部类型检查与借用检查,来确保比如这里没有传递某个 `String` 值,或传递某个无效引用到该函数。但 Rust *无法* 就该函数将准确完成咱们所想要的操作,即返回参数加 `2`,而非参数加 `10` 或者参数减去 `50` 进行检查!这正是测试发挥作用的地方。
|
||||
这并不意味着我们不应该尽可能多地测试!
|
||||
|
||||
可编写出进行假定的一些测试来,比如,在将 `3` 传递给这个 `add_two` 函数时,返回的值就是 `5`。每当修改了代码时,就都可以运行这些测试,来确保车关系的任何既有正确行为,没有发生变化。
|
||||
所谓程序的 *正确性*,是指我们的代码在多大程度上完成了我们想要他完成的事情。Rust 是在高度关注程序的正确性下设计的,但正确度很复杂且不易证明。Rust 的类型系统承担了这一负担的很大一部分,但类型系统并不能捕获所有问题。因此,Rust 提供了对编写自动化软件测试的支持。
|
||||
|
||||
测试是门综合技能:尽管这里无法在一章中,涉及到怎样编写良好测试的方方面面,这里还是会对 Rust 各种测试设施的机制进行讨论。这里会讲到在编写测试时,可用的注解与宏,运行测试的默认动作与选项,以及怎样将一些测试,组织为单元测试与集成测试(unit tests and integration tests)。
|
||||
假设我们编写了个函数 `add_two`,加 2 到传递给他的任何数字。这个函数的签名接受一个整数作为参数并返回一个整数作为结果。当我们实现并编译该函数时,Rust 会指定咱们迄今为止学过的所有类型检查与借用检查,以确保我们不会传递 `String` 值或无效引用给该函数。但 Rust *无法* 验证该函数是否将精确地执行咱们想要的操作,即返回参数加 2,而不是参数加 10 或参数减 50! 这就是测试派上用场的地方。
|
||||
|
||||
我们可以编写测试,断言比如当我们传递 `3` 给 `add_two` 函数时,返回值为 `5`。每当我们修改代码后,我们都可以运行这些测试,以确保任何现有的正确行为都没有改变。
|
||||
|
||||
测试属于一项复杂技能:虽然我们无法在一章中涵盖到怎样编写良好测试的每个细节,但在这一章中我们将讨论 Rust 的测试设施的各种机制。我们将探讨编写测试时可用的注解与宏、为运行测试提供的默认行为与选项,以及怎样组织测试为单元测试和集成测试。
|
||||
|
||||
|
||||
|
||||
@@ -516,7 +516,7 @@ where
|
||||
}
|
||||
```
|
||||
|
||||
这是 [清单 10-21](#listing_10-21) 中的 `longest` 函数,返回两个字符串切片中较长的那个。但现在他有个名为 `ann` 的泛型类型 `T` 的额外参数,可以由任何实现 `where` 子句指定的 `Display` 特质的类型填入。这个额外参数将使用 `{}` 打印出来,这就是为何 `Display` 特质边界是必要的。由与生命周期属于泛型类型,所以生命周期参数 `'a` 与泛型类型参数 `T` 的声明位于函数名字之后尖括号内的同一列表中。
|
||||
这是 [清单 10-21](#listing_10-21) 中的 `longest` 函数,返回两个字符串切片中较长的那个。但现在他有个名为 `ann` 的泛型类型 `T` 的额外参数,可以由任何实现 `where` 子句所指定的 `Display` 特质的类型填入。这个额外参数将使用 `{}` 打印出来,这就是为何 `Display` 特质边界是必要的。由与生命周期属于泛型类型,所以生命周期参数 `'a` 与泛型类型参数 `T` 的声明位于函数名字之后尖括号内的同一列表中。
|
||||
|
||||
|
||||
# 本章小结
|
||||
|
||||
Reference in New Issue
Block a user