前文连接:clean code-代码整洁之道 阅读笔记(第一章~第八章)-CSDN博客
第九章 单元测试
9.1 TDD 三定律
TDD 有广义和狭义之分,常说的是狭义的 TDD,也就是 UTDD(Unit Test Driven Development
)。广义的 TDD 是 ATDD
(Acceptance Test Driven Development
),包括 BDD
(Behavior Driven Development
)和 Consumer-Driven Contracts Development
等。
此处所说的 TDD 指狭义上的 TDD,也就是「单元测试驱动开发」。
TDD
是敏捷开发中的一项核心实践和技术,也是一种设计方法论。TDD的原理是在开发功能代码之前,先编写单元测试用例代码,测试代码确定需要编写什么产品代码 。TDD 是 XP(Extreme Programming)的核心实践。它的主要推动者是 Kent Beck
。
- 定律一 在编写不能通过的单元测试前,不可编写生产代码。
- 定律二 只可编写刚好不能通过的单元测试,不能编译也算不通过。
- 定律三 只可编写刚好足以通过当前失败测试的生产代码。
这三条定律将你限制在大概30秒一个的循环中。测试与生产代码一起编写,测试只比生产代码早写几秒钟。
这样写程序,测试将覆盖所有生产代码。测试代码量足以匹敌生产代码,导致管理问题。
9.2 保持测试整洁
测试代码和生产代码一样重要。它需要被思考、被设计和被照料。它该像生产代码一般保持整洁。
如果测试不干净,你改动自己代码的能力就有所牵制,而你也会开始失去改进代码结构的能力。测试越脏,代码就会变得越脏。最终,你丢失了测试,代码开始腐坏。
9.3 整洁的测试
整洁的测试有什么要素?有三个要素:可读性,可读性和可读性。
测试如何才能做到可读?和其他代码一样:明确,简洁,还有足够的表达力。
java
public void testGetPageHierarchyAsXml() throws Exceeption{
{
makePages("PageOne", "PageOne.Childone", "PageTwo");
submitRequest("root", "type:pages");
assertResponseIsXML();
assertResponseContains(
"<name>PageOne</name>", "<name>PageTwo</name>", "<name>Childone</name>"
);
}
public void testSymbolicLinksAreNotInXmlPageHierarchy() thnrows Exception{
WikiPage page makePage ("PageOne");
makePages("PageOne.Childone", "PageTwo");
addLinkTo(page, "PageTwo", "SymPage");
submitRequest("root", "type:pages");
assertResponseIsXML();
assertResponseContains(
"<name>PageOne</name>", "<name>PageTwo</name>", "<name>ChildOne</name>"
);
assertResponseDoesNotContain("SymPage");
}
public void testGetDataAsXml()throws Exception{
makePageWith Content("TestPageOne", "test page");
submitRequest("TestPageOne", "type:data");
assertResponseIsXML();
assertResponseContains("test page","<Test");
}
这些测试显然呈现了构造-操作-检验(BUILD-OPERATE-CHECK)模式。每个测试都清晰地拆分为三个环节。第一个环节构造测试数据,第二个环节操作测试数据,第三个部分检验操作是否得到期望的结果。
9.3.1 面向特定领域的测试语言
代码中的测试展示了为测试构造一种面向特定领域的语言的技巧。我们没有直接使用程序员用来对系统进行操作的API,而是打造了一套包装这些API的函数和工具代码,这样就能更方便地编写测试,写出来的测试也更便于阅读。那正是一种测试语言,可以帮助程序员编写自己的测试,也可以帮助后来者阅读测试。
这种测试API并非起初就设计出来,而是在对那些充满令人迷惑细节的测试代码进行后续重构时逐渐演进。守规矩的开发者也将他们的测试代码重构为更简洁和具有表达力的形式。
9.3.2 双重标准
测试API中的代码与生产代码相比,有一套不同的工程标准。测试代码应当简单、精悍、足具表达力,但它该和生产代码一般有效。毕竟它是在测试环境而非生产环境中运行,这两种环境有着截然不同的需求。
有些事你大概永远不会在生产环境中做,而在测试环境中做却完全没问题。通常这关乎内存或CPU效率的问题,不过却永远不会与整洁有关。
9.4 每个测试一个断言
尽可能减少每个概念的断言数量,每个测试函数只测试一个概念。
9.5 F.I.R.S.T.
整洁的测试还遵循以下5条规则:
- **快速(Fast)**测试应该够快。测试 应该能快速运行。
- **独立(Independent)**测试应该相互独立。
- 可重复(Repeatable) 测试应当可在任何环境中重复通过。
- **自足验证(Self-Validating)**测试应该有布尔值输出。
- **及时(Timely)**测试应及时编写。
如果你坐视测试腐坏,那么代码也会跟着腐坏。保持测试整洁吧。