提交 600c000f 编写于 作者: W wizardforcel

2021-10-01 21:55:42

上级 6ad7abe6
# 为什么我应该关心测试驱动的开发?
这本书是由开发人员为开发人员编写的。因此,大部分学习将通过代码进行。每章将介绍一个或多个**t****est 驱动开发****TDD**实践,我们将通过解决**katas**来尝试掌握它们。在空手道中,空手道是一种练习,你重复一个动作很多次,每次都没有什么进步。遵循同样的理念,我们将从一章到下一章进行小而重要的改进。您将学习如何更好地设计和编写代码,缩短**上市时间****TTM**),生成始终最新的文档,通过质量测试获得高代码覆盖率,并编写干净有效的代码。
这本书是由开发人员为开发人员编写的。因此,大部分学习将通过代码进行。每章将介绍一个或多个**测试驱动开发****TDD**实践,我们将通过解决**katas**来尝试掌握它们。在空手道中,空手道是一种练习,你重复一个动作很多次,每次都没有什么进步。遵循同样的理念,我们将从一章到下一章进行小而重要的改进。您将学习如何更好地设计和编写代码,缩短**上市时间****TTM**),生成始终最新的文档,通过质量测试获得高代码覆盖率,并编写干净有效的代码。
每一次旅行都有一个开始,这次也不例外。我们的目标是一个拥有 TDD 黑带的 Java 开发人员。
......@@ -51,7 +51,7 @@ TDD 加快了上市时间,实现了更容易的重构,有助于创建更好
# 理解 TDD
此时,你可能在对自己说,*好吧,我知道 TDD 会给我带来一些好处,但 TDD 到底是什么?*TDD 是在实际实施之前编写测试的简单过程。它与传统方法相反,传统方法是在编写代码后执行测试。
此时,你可能在对自己说,“好吧,我知道 TDD 会给我带来一些好处,但 TDD 到底是什么?”TDD 是在实际实施之前编写测试的简单过程。它与传统方法相反,传统方法是在编写代码后执行测试。
# 红绿重构
......@@ -148,7 +148,7 @@ TDD 的主要目标是可测试的代码设计,将测试作为非常有用的
# 质量检查和质量保证之间的区别
测试方法也可以通过查看他们试图实现的目标来区分。这些目标通常分为**质量检查****质量控制**)和**质量保证****质量保证**)。当 QC 关注缺陷识别时,QA 试图防止缺陷。QC 以产品为导向,旨在确保结果符合预期。另一方面,QA 更关注于确保内在质量的过程。它试图确保以正确的方式做正确的事情。
测试方法也可以通过查看他们试图实现的目标来区分。这些目标通常分为**质量检查****QC**)和**质量保证****QA**)。当 QC 关注缺陷识别时,QA 试图防止缺陷。QC 以产品为导向,旨在确保结果符合预期。另一方面,QA 更关注于确保内在质量的过程。它试图确保以正确的方式做正确的事情。
虽然 QC 在过去扮演着更重要的角色,但随着 TDD 的出现,**验收测试驱动开发****ATDD**),以及后来的 BDD,焦点已经转向 QA。
......@@ -184,7 +184,7 @@ TDD(通常是结构良好的测试)的另一个非常有用的方面是文
测试是可执行文档,TDD 是创建和维护它的最常用方法。
假设正在使用某种形式的**续集成****CI**),如果测试文档的某些部分不正确,它将失败,并很快得到修复。CI 解决了测试文档不正确的问题,但它不能确保所有功能都被文档化。出于这个原因(在许多其他原因中),测试文档应该以 TDD 方式创建。如果在编写实现代码之前将所有功能定义为测试,并且所有测试的执行都是成功的,那么测试将充当开发人员可以使用的完整且最新的信息源。
假设正在使用某种形式的**续集成****CI**),如果测试文档的某些部分不正确,它将失败,并很快得到修复。CI 解决了测试文档不正确的问题,但它不能确保所有功能都被文档化。出于这个原因(在许多其他原因中),测试文档应该以 TDD 方式创建。如果在编写实现代码之前将所有功能定义为测试,并且所有测试的执行都是成功的,那么测试将充当开发人员可以使用的完整且最新的信息源。
我们应该如何对待团队的其他成员?测试人员、客户、经理和其他非编码人员可能无法从生产和测试代码中获得必要的信息。
......
......@@ -195,7 +195,7 @@ gradle test
# 综合发展环境
由于将涉及许多工具和技术,我们建议使用 IntelliJ IDEA 作为代码开发工具。主要原因是这个**集成开发环境****IDE**工作时没有任何繁琐的配置。社区版(IntelliJ IDEA CE)提供了一系列内置功能和插件,使编码变得简单高效。它会根据文件扩展名自动推荐可安装的插件。由于 IntelliJ IDEA 是我们为本书所做的选择,因此您将找到有关其操作或菜单的参考资料和步骤。如果读者正在使用其他 IDE,他们应该找到一种适当的方法来模拟这些步骤。参见[这里](https://www.jetbrains.com/idea/)获取有关如何下载和安装 IntelliJ IDEA 的说明。
由于将涉及许多工具和技术,我们建议使用 IntelliJ IDEA 作为代码开发工具。主要原因是这个**集成开发环境****IDE**工作时没有任何繁琐的配置。社区版(IntelliJ IDEA CE)提供了一系列内置功能和插件,使编码变得简单高效。它会根据文件扩展名自动推荐可安装的插件。由于 IntelliJ IDEA 是我们为本书所做的选择,因此您将找到有关其操作或菜单的参考资料和步骤。如果读者正在使用其他 IDE,他们应该找到一种适当的方法来模拟这些步骤。参见[这里](https://www.jetbrains.com/idea/)获取有关如何下载和安装 IntelliJ IDEA 的说明。
# 创意演示项目
......@@ -925,7 +925,7 @@ public class SelenideTest {
一个故事由情景组成。每个场景代表一个简明的行为用例,并使用步骤以自然语言编写。步骤是场景的先决条件、事件和结果的序列。每个步骤必须以单词`Given``When``Then`开头。`Given`表示先决条件,`When`表示动作,`Then`表示执行验证。
这只是一个简短的介绍。有一整章,第 8 章*BDD–与整个团队*一起工作,致力于此主题。现在是时候介绍 JBehave 和 Cucumber 了,它们是许多用于编写和执行故事的可用框架中的两个。
这只是一个简短的介绍。有一整章,第 8 章“BDD–与整个团队一起工作”,致力于此主题。现在是时候介绍 JBehave 和 Cucumber 了,它们是许多用于编写和执行故事的可用框架中的两个。
# 杰伯哈夫
......
......@@ -4,7 +4,7 @@
–李小龙
**红绿重构**技术是**测试驱动开发****TDD**的基础。这是一个乒乓球游戏,我们在测试和实现代码之间快速切换。我们会失败,然后我们会成功,最后,我们会进步。
**红绿重构**技术是**测试驱动开发****TDD**的基础。这是一个乒乓球游戏,我们在测试和实现代码之间快速切换。我们会失败,然后我们会成功,最后,我们会进步。
我们将开发一个 Tic-Tac-Toe 游戏,每次检查一个需求。我们将编写一个测试,看看它是否失败。然后,我们将编写实现该测试的代码,运行所有测试,并看到它们成功。最后,我们将重构代码并尝试使其更好。该过程将重复多次,直到所有需求都成功实现。
......@@ -72,7 +72,7 @@ dependencies {
Maven 和 Gradle 等构建工具需要源目录、分离以及命名约定。
就这样。我们准备开始使用 JUnit 作为首选的测试框架,使用 Gradle 进行编译、依赖、测试和其他任务,开发我们的 Tic-Tac-Toe 应用程序。在第 1 章*我为什么要关注测试驱动开发?*,您首先遇到了红-绿重构过程。因为它是 TDD 的基石,也是本章练习的主要目标,所以在我们开始开发之前,深入了解更多细节可能是一个好主意。
就这样。我们准备开始使用 JUnit 作为首选的测试框架,使用 Gradle 进行编译、依赖、测试和其他任务,开发我们的 Tic-Tac-Toe 应用程序。在第 1 章“我为什么要关注测试驱动开发?”中,您首先遇到了红-绿重构过程。因为它是 TDD 的基石,也是本章练习的主要目标,所以在我们开始开发之前,深入了解更多细节可能是一个好主意。
# 红绿重构过程
......
......@@ -6,7 +6,7 @@
正如所承诺的,每一章都将探讨不同的 Java 测试框架,这一章也不例外。我们将使用 TestNG 来构建我们的规范。
在前面的第 3 章*红绿重构——从失败到成功直到完美*中,我们实践了红绿重构过程。我们使用了单元测试,但没有深入探讨单元测试在 TDD 环境中是如何工作的。我们将以上一章的知识为基础,通过解释单元测试到底是什么,以及它们如何适合于构建软件的 TDD 方法,来进行更详细的讨论。
在前面的第 3 章“红绿重构——从失败到成功直到完美”中,我们实践了红绿重构过程。我们使用了单元测试,但没有深入探讨单元测试在 TDD 环境中是如何工作的。我们将以上一章的知识为基础,通过解释单元测试到底是什么,以及它们如何适合于构建软件的 TDD 方法,来进行更详细的讨论。
本章的目标是学习如何专注于我们目前正在工作的单元,以及如何忽略或隔离以前做过的单元。
......@@ -26,11 +26,11 @@
# 什么是单元测试?
**单元测试**是一种迫使我们测试小型、独立和孤立的代码单元的实践。它们通常是方法,即使在某些情况下类甚至整个应用程序也可以被视为单元。为了编写单元测试,测试中的代码需要与应用程序的其余部分隔离。最好,这种隔离已经在代码中根深蒂固,或者可以通过使用**模拟**(更多关于模拟的内容将在第 6 章、*模拟–移除外部依赖*中介绍)。如果特定方法的单元测试跨越该单元的边界,那么它们就成为集成测试。因此,测试内容变得不那么清晰。在发生故障的情况下,问题的范围突然扩大,查找原因变得更加乏味。
**单元测试**是一种迫使我们测试小型、独立和孤立的代码单元的实践。它们通常是方法,即使在某些情况下类甚至整个应用程序也可以被视为单元。为了编写单元测试,测试中的代码需要与应用程序的其余部分隔离。最好,这种隔离已经在代码中根深蒂固,或者可以通过使用**模拟**(更多关于模拟的内容将在第 6 章、“模拟–移除外部依赖”中介绍)。如果特定方法的单元测试跨越该单元的边界,那么它们就成为集成测试。因此,测试内容变得不那么清晰。在发生故障的情况下,问题的范围突然扩大,查找原因变得更加乏味。
# 为什么要进行单元测试?
一个常见的问题,特别是在严重依赖手动测试的组织中,是*为什么我们应该使用单元而不是功能和集成测试?*这个问题本身是有缺陷的。单元测试不能取代其他类型的测试。相反,单元测试缩小了其他类型测试的范围。从本质上讲,单元测试比任何其他类型的测试都更容易、更快地编写,从而降低了成本和**上市时间****TTM**。由于编写和运行它们的时间缩短,它们往往能够更快地检测到问题。我们发现问题的速度越快,解决问题的成本就越低。一个在创建几分钟后检测到的 bug 要比在创建几天、几周甚至几个月后发现的 bug 更容易修复。
一个常见的问题,特别是在严重依赖手动测试的组织中,是“为什么我们应该使用单元而不是功能和集成测试?”这个问题本身是有缺陷的。单元测试不能取代其他类型的测试。相反,单元测试缩小了其他类型测试的范围。从本质上讲,单元测试比任何其他类型的测试都更容易、更快地编写,从而降低了成本和**上市时间****TTM**。由于编写和运行它们的时间缩短,它们往往能够更快地检测到问题。我们发现问题的速度越快,解决问题的成本就越低。一个在创建几分钟后检测到的 bug 要比在创建几天、几周甚至几个月后发现的 bug 更容易修复。
# 代码重构
......@@ -64,7 +64,7 @@ TDD 迫使我们仔细考虑我们的需求和设计,编写干净有效的代
# TestNG
JUnit 和 TestNG 是两个主要的 Java 测试框架。在上一章第 3 章*红绿色重构中,您已经使用 JUnit 编写了测试——从失败到成功,直到完美*,并且,希望您能够很好地理解它的工作原理。TestNG 怎么样?它的诞生是为了让 JUnit 变得更好。实际上,它包含一些 JUnit 没有的功能。
JUnit 和 TestNG 是两个主要的 Java 测试框架。在上一章第 3 章“红绿重构”中,您已经使用 JUnit 编写了测试——从失败到成功,直到完美*,并且,希望您能够很好地理解它的工作原理。TestNG 怎么样?它的诞生是为了让 JUnit 变得更好。实际上,它包含一些 JUnit 没有的功能。
以下小节总结了两者之间的一些差异。我们将尝试不仅解释这些差异,还将在使用 TDD 进行单元测试的上下文中对它们进行评估。
......@@ -112,7 +112,7 @@ JUnit 和 TestNG 都可以禁用测试。JUnit 使用单独的`@Ignore`注释,
# @Test(expectedExceptions=SomeClass.class)注释参数
这就是 JUnit 的优势所在。虽然两者都提供了相同的方法来指定预期的异常(在 JUnit 的情况下,参数被简单地称为`expected`,但 JUnit 引入的规则是测试异常的一种更优雅的方式(我们已经在第 2 章、*工具、框架和环境*中使用过它们)。
这就是 JUnit 的优势所在。虽然两者都提供了相同的方法来指定预期的异常(在 JUnit 的情况下,参数被简单地称为`expected`,但 JUnit 引入的规则是测试异常的一种更优雅的方式(我们已经在第 2 章、“工具、框架和环境”中使用过它们)。
# TestNG 与 JUnit 摘要
......@@ -132,7 +132,7 @@ TestNG 提供了更多的特性,并且比 JUnit 更高级。在本章中,我
我们的工作将是创建一个可以在海上移动船舶的程序。
因为这是一本 TDD 书籍,本章的主题是单元测试,所以我们将使用 TDD 方法开发一个应用程序,重点是单元测试。在上一章第 3 章*红绿重构——从失败到成功,直到完美*中,您学习了红绿重构过程的理论和实践经验。我们将在此基础上进一步学习如何有效地使用单元测试。具体地说,我们将试着专注于我们正在开发的单元,并学习如何隔离和忽略单元可能使用的依赖项。不仅如此,我们还将努力一次只关注一个需求。出于这个原因,您只收到了高级别的需求;我们应该能够移动位于地球某处的遥控飞船。
因为这是一本 TDD 书籍,本章的主题是单元测试,所以我们将使用 TDD 方法开发一个应用程序,重点是单元测试。在上一章第 3 章“红绿重构——从失败到成功,直到完美”中,您学习了红绿重构过程的理论和实践经验。我们将在此基础上进一步学习如何有效地使用单元测试。具体地说,我们将试着专注于我们正在开发的单元,并学习如何隔离和忽略单元可能使用的依赖项。不仅如此,我们还将努力一次只关注一个需求。出于这个原因,您只收到了高级别的需求;我们应该能够移动位于地球某处的遥控飞船。
为了让事情变得更简单,所有的支持类都已经制作并测试过了。这将使我们能够集中精力完成手头的主要任务,同时保持这项工作的简洁
......@@ -212,7 +212,7 @@ public Location(Point point, Direction direction) {
}
```
知道了这一点,为第一个需求编写测试应该相当容易。我们应该像上一章一样工作,第 3 章*红绿重构——从失败到成功,直到完美*
知道了这一点,为第一个需求编写测试应该相当容易。我们应该像上一章一样工作,第 3 章“红绿重构——从失败到成功,直到完美”
试着自己编写规范。完成后,将其与本书中的解决方案进行比较。对实现规范的代码重复相同的过程。试着自己写,完成后,将其与我们提出的解决方案进行比较。
......
......@@ -419,7 +419,7 @@ private void checkWinCondition(int col, int row) {
# 汉克雷斯特
如第 2 章、*工具、框架和环境*所述,Hamcrest 提高了我们测试的可读性。通过使用**匹配器**降低复杂性,使断言更具语义性和全面性。当测试失败时,通过解释断言中使用的匹配器,显示的错误变得更具表现力。开发人员还可以添加一条消息。
如第 2 章、“工具、框架和环境”所述,Hamcrest 提高了我们测试的可读性。通过使用**匹配器**降低复杂性,使断言更具语义性和全面性。当测试失败时,通过解释断言中使用的匹配器,显示的错误变得更具表现力。开发人员还可以添加一条消息。
`Hamcrest`库中充满了针对不同对象类型和集合的不同匹配器。让我们开始编码并体验一下。
......
......@@ -796,7 +796,7 @@ public String play(int x, int y) {
正如您可能猜到的那样,集成测试的目标是验证独立组件、应用程序、系统等的集成。如果您还记得测试金字塔,它指出单元测试是最容易编写和运行最快的,因此我们应该将其他类型的测试限制在 UTs 没有涵盖的范围内。
我们应该以一种可以偶尔运行的方式隔离我们的集成测试(在我们将代码推送到存储库之前,或者作为我们的**续集成****CI**)过程的一部分),并将单元测试保持为一个连续反馈循环。
我们应该以一种可以偶尔运行的方式隔离我们的集成测试(在我们将代码推送到存储库之前,或者作为我们的**续集成****CI**)过程的一部分),并将单元测试保持为一个连续反馈循环。
# 试验分离
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册