所有程序员都知道应该做单元测试,但为什么你们没有做呢?是因为对单元测试不够了解,还是嫌单元测试麻烦,抑或认为单元测试的投入产出比太低?不管因为什么,你都应该看看这本书。
本书在第1版基础上新增了很多内容,不过仍然会手把手地教你从第一个单元测试开始写起,通过简单的例子让你理解如何编写好维护、易明白和可靠的单元测试。在此基础上,本书自然过渡到一些较为高级的主题,比如模拟对象、存根和隔离框架(Moq、FakeItEasy和Typemock Isolator等),同时涉及测试模式,以及组织、重构代码的技巧,乃至怎么测试“不可测试”的代码。另外,其中还介绍了集成测试和关联数据库的测试技术。
本书代码示例虽然是用C#写的,但有关单元测试的技术和思想适合所有使用静态类型语言(如VB.NET、Java、C++)的测试人员,以及测试驱动开发人员学习借鉴。
主要内容:
创建可读、可维护和可靠的测试
伪对象、存根、模拟对象和隔离(模拟)框架
简单的依赖注入技术
重构遗留代码
第2版新增:
受限与不受限的隔离框架及其工作原理
隔离框架的特征及Typemock等框架的内部工作机制
更多实施单元测试的可用技术
调优示例代码的设计(避免使用属性设置方法,转而使用构造函数注入)
点到为止,探讨SOLID原则
构建自动化及测试模式
对设计与可测试性的新认识
更新工具与框架(附录A)
第一部分 入门
第1章 单元测试基础2
1.1 逐步定义单元测试2
1.1.1 编写优秀单元测试的重要性4
1.1.2 我们都写过(某种)单元测试4
1.2 优秀单元测试的特性5
1.3 集成测试5
1.4 什么是优秀的单元测试9
1.5 一个简单的单元测试范例9
1.6 测试驱动开发12
1.7 成功进行TDD的三种核心技能15
1.8 小结15
第2章 第一个单元测试17
2.1 单元测试框架18
2.1.1 单元测试框架提供什么18
2.1.2 xUnit框架20
2.2 LogAn项目介绍20
2.3 NUnit初步20
2.3.1 安装NUnit21
2.3.2 加载解决方案22
2.3.3 在代码中使用NUnit属性24
2.4 编写第一个测试25
2.4.1 Assert类25
2.4.2 用NUnit运行第一个测试26
2.4.3 添加正检验27
2.4.4 从红到绿:测试成功28
2.4.5 测试代码格式28
2.5 使用参数重构测试28
2.6 更多NUnit属性30
2.6.1 setup和teardown30
2.6.2 检验预期的异常33
2.6.3 忽略测试35
2.6.4 NUnit的方法语法36
2.6.5 设置测试类别37
2.7 测试系统状态的改变而非返回值37
2.8 小结41
第二部分 核心技术
第3章 使用存根破除依赖44
3.1 存根简介44
3.2 发现LogAn中对文件系统的依赖45
3.3 如何使测试LogAnalyzer变得容易46
3.4 重构代码设计以提高可测试性48
3.4.1 抽取接口使底层实现可替换49
3.4.2 依赖注入:在被测试单元中注入一个伪实现51
3.4.3 在构造函数层注入一个伪对象(构造函数注入)51
3.4.4 用伪对象模拟异常55
3.4.5 用属性get或set注入伪对象56
3.4.6 在方法调用前注入伪对象57
3.5 重构技术变种63
3.6 克服封装问题65
3.6.1 使用internal和[InternalsVisibleTo]65
3.6.2 使用[Conditional]属性66
3.6.3 使用#if和#endif进行条件编译66
3.7 小结67
第4章 使用模拟对象进行交互测试68
4.1 基于值的测试、基于状态的测试和交互测试68
4.2 模拟对象和存根的区别70
4.3 手工模拟对象的简单示例71
4.4 同时使用模拟对象和存根73
4.5 每个测试一个模拟对象78
4.6 伪对象链:用存根生成模拟对象或其他存根78
4.7 手工模拟对象和存根的问题79
4.8 小结80
第5章 隔离(模拟)框架81
5.1 为什么要使用隔离框架81
5.2 动态生成伪对象83
5.2.1 在测试中使用NSubstitute83
5.2.2 用动态伪对象替换手工伪对象84
5.3 模拟值86
5.4 测试事件相关的活动92
5.4.1 测试事件监听者92
5.4.2 测试事件是否触发93
5.5 现有的.NET隔离框架94
5.6 隔离框架的优缺点95
5.6.1 使用隔离框架时应避开的陷阱96
5.6.2 测试代码不可读96
5.6.3 验证错误的事情96
5.6.4 一个测试多个模拟对象96
5.6.5 过度指定测试97
5.7 小结97
第6章 深入了解隔离框架99
6.1 受限框架及不受限框架99
6.1.1 受限框架99
6.1.2 不受限框架100
6.1.3 基于探查器的不受限框架如何工作101
6.2 优秀隔离框架的价值103
6.3 支持适应未来和可用性的功能103
6.3.1 递归伪对象104
6.3.2 默认忽略参数104
6.3.3 泛伪造105
6.3.4 伪对象的非严格行为105
6.3.5 非严格模拟对象106
6.4 隔离框架设计反模式106
6.4.1 概念混淆106
6.4.2 录制和重放107
6.4.3 粘性行为109
6.4.4 复杂语法109
6.5 小结109
第三部分 测试代码
第7章 测试层次和组织112
7.1 运行自动化测试的自动化构建112
7.1.1 构建脚本结构113
7.1.2 触发构建和集成115
7.2 基于速度和类型布局测试116
7.2.1 分离集成测试和单元测试的人为因素117
7.2.2 绿色安全区117
7.3 确保测试是源代码管理的一部分118
7.4 将测试类映射到被测试代码118
7.4.1 将测试映射到项目118
7.4.2 将测试映射到类118
7.4.3 将测试映射到具体的工作单元入口119
7.5 注入横切关注点120
7.6 为应用程序构建测试API122
7.6.1 使用测试类继承模式122
7.6.2 创建测试工具类和方法133
7.6.3 把你的API介绍给开发人员134
7.7 小结134
第8章 优秀单元测试的支柱136
8.1 编写可靠的测试136
8.1.1 决定何时删除或修改测试137
8.1.2 避免测试中的逻辑140
8.1.3 只测试一个关注点142
8.1.4 把单元测试和集成测试分开143
8.1.5 用代码审查确保代码覆盖率143
8.2 编写可维护的测试144
8.2.1 测试私有或受保护的方法145
8.2.2 去除重复代码146
8.2.3 以可维护的方式使用setup方法149
8.2.4 实施测试隔离151
8.2.5 避免对不同关注点多次断言156
8.2.6 对象比较158
8.2.7 避免过度指定160
8.3 编写可读的测试162
8.3.1 单元测试命名162
8.3.2 变量命名163
8.3.3 有意义的断言164
8.3.4 断言和操作分离165
8.3.5 setup和teardown165
8.4 小结166
第四部分 设计和流程
第9章 在组织中引入单元测试168
9.1 逐步成为变革的倡导者168
9.1.1 准备好面对质疑169
9.1.2 说服组织内成员:支持者和反对者169
9.1.3 找到可能的切入点169
9.2 成功之道171
9.2.1 游击式实现(自下而上)171
9.2.2 说服高层(自上而下)171
9.2.3 引入外援172
9.2.4 使进度可见172
9.2.5 设定具体目标173
9.2.6 应对障碍175
9.3 失败原因175
9.3.1 缺少驱动力175
9.3.2 缺乏政策支持175
9.3.3 不好的实现和第一印象176
9.3.4 缺少团队支持176
9.4 影响因素176
9.5 质疑和回答177
9.5.1 单元测试会给现有流程增加多少时间178
9.5.2 单元测试是否会抢了QA饭碗179
9.5.3 证明单元测试确实有效的方法179
9.5.4 单元测试有用的证据180
9.5.5 QA部门还是能找到缺陷的原因180
9.5.6 我们有大量没有测试的代码:应该从哪里开始181
9.5.7 我们使用多种编程语言:单元测试是否可行181
9.5.8 软硬件结合的开发181
9.5.9 确保测试中没有缺陷的方法181
9.5.10 我的代码已经调试通过了,但还需要测试的原因182
9.5.11 驱动开发测试的必要性182
9.6 小结182
第10章 遗留代码183
10.1 从哪里开始增加测试183
10.2 决定选择策略185
10.2.1 先易后难策略的优缺点185
10.2.2 先难后易策略的优缺点186
10.3 在重构前编写集成测试186
10.4 遗留代码单元测试的重要工具187
10.4.1 使用不受限的隔离框架轻松隔离依赖项187
10.4.2 使用JMockit测试Java遗留代码189
10.4.3 重构Java代码时使用Vise190
10.4.4 重构前使用验收测试191
10.4.5 阅读Michael Feathers关于遗留代码的书192
10.4.6 使用NDepend调查产品代码192
10.4.7 使用ReSharper浏览和重构产品代码192
10.4.8 使用Simian和TeamCity发现重复代码(和缺陷)193
10.5 小结193
第11章 设计与可测试性194
11.1 为什么在设计时要关心可测试性194
11.2 可测试性的设计目标195
11.2.1 默认情况下将方法设置为虚拟方法195
11.2.2 使用基于接口的设计196
11.2.3 默认情况下将类设置为非密封的196
11.2.4 避免在包含逻辑的方法内初始化具体类197
11.2.5 避免直接调用静态方法197
11.2.6 避免在构造函数和静态构造函数中包含逻辑代码197
11.2.7 把单例逻辑和单例持有者分开198
11.3 可测试性设计的利弊199
11.3.1 工作量199
11.3.2 复杂度200
11.3.3 泄露敏感知识产权200
11.3.4 有时无法实现200
11.4 可测试性设计的替代方法200
11.5 难以测试的设计示例202
11.6 小结205
11.7 更多资源206
附录A 工具和框架208
《襄言随语:地方经济社会科学发展与改革创新》内容简介:本书是作者在湖北省襄阳市及随州市任职期间公开发表的讲话、报告、随笔集
D语言是一种通用的系统和应用编程语言,它保持了生成高效代码以及直接访问操作系统API和硬件的能力。《D程序设计语言》是一本介绍
数据结构(C语言版)(配光盘) 本书特色 《清华大学计算机系列教材:数据结构(C语言版)》可作为计算机类专业或信息类相关专业的本科或专科教材,也可供从事计算机工...
SAP入门经典-(第5版) 本书特色 《SAP入门经典(第5版)》是由业内专家编写的SAP入门教程,其中对SAP的各种主要产品与组件进行了较为详细的介绍,并且从...
《金湖大合唱钢琴伴奏合唱谱》内容简介:这部交响音诗是作者在深入大、小兴安岭和长白山地区采风获得灵感所作,作者根据自己的选材
《西南联大历史通识课》内容简介:★西南联大博物馆官方认证版 ★1937—2022,西南联大建校85周年纪念 ★大师摇篮,世界教育史上的
《围观考古现场》内容简介:翻开这本书之前,请你思考一个问题:考古学究竟是一门怎样的学问?是挖坟掘墓找古董?是翻山越岭看岩壁
UDA是一种专门为提高并行程序开发效率而设计的计算架构。在构建高性能应用程序时,CUDA架构能充分发挥GPU的强大计算功能。《GPU高
NeedtoLearnMATLAB?ProblemSOLVED!GetstartedusingMATLABrightawayw...
CSS是层叠样式表的简称,通过它可控制网页样式并允许将样式信息与网页内容分离。《CSS终极参考手册》是CSS的最佳参考书籍,共18章
《梁思成中国建筑史》内容简介:★首部中国人自己书写的本民族建筑史 ★中国现代建筑学的奠基之作 ★国徽设计者、中国现代建筑之父
《楚辞》内容简介:本书是我国第一部浪漫主义诗歌总集,由西汉文学家刘向主编,收录了屈原、宋玉的作品以及汉代东方朔、王褒、刘向
《画出来的箴言》批判了现代艺术发展过程中某些虚伪可笑的现象:艺术被功利化,被用来欺蒙大众;富人们追求现代艺术只是赶时髦;
《孩子咳嗽,自然疗法80种》内容简介:运用自然疗法,调动孩子身体的自愈能力,不仅治咳嗽更养生咳嗽并不是疾病,而是疾病的一种症
《TRIZ:产品创新设计》内容简介:开发出有竞争力的产品,是制造业企业提高自身竞争优势的重要保障因素。在模糊前端和新产品开发、
《世界名著大师课:俄罗斯卷》内容简介:本书是世界文学领域的翻译家、权威学者们对俄语文学史上最具有代表性的11部名著的深入解读
《理性的设计感性的空间:法国DBLANT都林国际设计》贯穿了30余篇设计师的文章,对设计机构的发展模式、设计项目的管理及设计过程中
本书全面而系统地介绍了安藤忠雄的作品,包括他从成名以来到现在的一些代表作以及他最新的一些作品。书中所用的图纸和资料都由安藤
《经典密码学与现代密码学》主要从三个方面来介绍密码学的知识:第一部分介绍了经典密码学的经典问题,包括单码加密法、仿射加密
《Ghidra权威指南》内容简介:Ghidra是美国国家安全局(NSA)开发的一套逆向工程工具套件。本书是目前市面上仅有的一本Ghidra使用指