基本信息
- 原书名:Effective Unit Testing: A guide for Java Developers
- 原出版社: Manning Publications
- 作者: (芬)Lasse Koskela
- 译者: 申健
- 丛书名: 华章程序员书库
- 出版社:机械工业出版社
- ISBN:9787111483434
- 上架时间:2014-11-5
- 出版日期:2014 年11月
- 开本:16开
- 页码:198
- 版次:1-1
- 所属分类:计算机 > 软件工程及软件方法学 > 设计模式

编辑推荐
资深敏捷技术实践专家撰写,系统且深入地阐释单元测试用于软件设计的工具、方法、原则和最佳实践。
深入剖析各种测试常见问题,包含大量实践案例,可操作性强,能为用户高效编写优秀测试提供系统实践指南。
内容简介
计算机书籍
这是一本关于单元测试的系统实践指南,由资深敏捷技术实践专家撰写,不仅全面阐释了单元测试用于软件设计的工具、方法、原则和最佳实践,而且对各种测试常见问题进行了深入分析,包含大量实践案例,可操作性强,能为用户高效编写优秀测试提供有效指导,让组织持续创造成功的产品和服务。
本书分为三部分,共9章。第一部分(第1—3章)主要阐述测试的目的与原因,并分析作为常用工具的测试替身的作用。第1章先从整体阐释测试先行所带来的价值,以及各种对测试和测试质量的影响,,第2章定义如何才能写出优秀的测试。第3章讨沦现代程序员最基本的工具之一——测试替身。第二部分(第4—6章)的目标是帮助我们更好地识别并修复测试代码中的坏味道。第4章展示破坏测试可读性的坏味道。第5章继续对破坏可维护性的测试提供建议。第6章涉及有关脆弱或不可靠的测试坏味道。第三部分(第7—9章)涉~Java程序员在编写测试时随时可能碰到的话题。第7章介绍可测的设汁的定义与作用。第8章探讨JVM语言的共生,以及如何用另一门语言来测试Java代码。第9章专门讨论对构建进行加速的问题。此外还包括两个附录,附录A介绍使用JUnit编写测试的入门知识。附录B探讨通过JUnit的API来扩展其内置功能。
作译者
申健 江湖人称“申导”,创客、王匠、敏捷教练、软件开发顾问,致力于启发创意、促进协作、交付价值的事业。
1994年迷上汁算机编程。从南京大学毕业后,在跨国企业从事近十年的研发和管理工作,涉及通信、金融、互联网等领域,拥有丰富的移动应用程序和面向服务分布式系统的项目经验,擅长使用不同的技术来实现面向服务的分布式架构设计和整体解决方案,熟悉J2EE、Python、嵌入式C、 Node.js技术及iOS等平台。2007年开始进入敏捷开发实践,拥有CSP、CSM和CSPO等认证。他曾在诺基亚西门子担任高级工程师和研发经理,在渣打银行担任资深工程师和敏捷教练等。
目前主要从事外部敏捷教练工作,提供组织转型和技术实践的咨询与培训服务。同时还是Scrum Aliiance注册讲师、1nfoQ中文站编辑、中国敏捷教练组成员,以及敏捷之旅、 ScrumGathering、QClub等社区活动的讲师与组织者。他曾翻译《SOA with REST》等书籍。
个人网站:www.JackyShen.com
目录
译者序
序言
前言
致谢
第一部分 基础
第1章 优秀测试的承诺 2
1.1 国情咨文:编写更好的测试 3
1.2 测试的价值 3
1.2.1 生产力的因素 6
1.2.2 设计潜力的曲线 8
1.3 测试作为设计工具 9
1.3.1 测试驱动开发 9
1.3.2 行为驱动开发 11
1.4 小结 12
第2章 寻求优秀 13
2.1 可读的代码才是可维护的代码 14
2.2 结构有助于理解事物 16
2.3 如果测试了错误的东西就不好了 17
2.4 独立的测试易于单独运行 18
译者序
随着敏捷开发大潮的流行,单元测试也成了现代软件开发中必不可少的工具之一。古人云,流水不腐,户枢不蠹。越来越多的程序员推崇自动化测试的理念,作为经济合理的回归测试手段,以适应迭代开发的需要。然而有些时候,这些测试对生产力并无明显改善,人们盲目地追求测试覆盖率,却忽视了测试代码的质量,各种无效单元测试反而带来了沉重的维护负担。
2013年年初,一位远在新加坡的印度朋友Ram就推荐我看过本书的英文版,当时完整读了一遍,觉得该书深入浅出,覆盖了很多关于编写优秀单元测试的内容,而且总结得很有条理。没想到的是,2013年下半年,出版社的编辑找到我说有一本书愿不愿翻译,没想到正是本书!既然有缘,当时就答应了下来。
本以为半年可以完成翻译,却没想到过去的12个月里生活和工作出现各种变化与惊喜,于是翻译工作一拖再拖,进展不快。
2014年6月Scrum Gathering大会在上海召开,作为话题演讲的总制作人和大会讲师,原想书能尽快出版,就可以带去一些回馈社区,只可惜没能实现,又让朋友们多等了几个月。
目前,我从事敏捷教练和培训的工作,同时通过动手实践仍在不断提高自己的编程水平。希望借此机会,将我过去几年的敏捷实践经验分享给更多人。
个人喜欢和敏捷社区的软件匠友动手切磋,一起编写高质量代码,另外在讲授CSD(认证Scrum开发者或称敏捷技术实践)课程时,也经常会接触来自不同行业的软件开发者。在这个过程中,我们发现,审美之前有必要先学审丑。好的编码模式各有千秋,能抓到老鼠的就是好猫。然而,坏的模式却是有限的。
本书作者Lasse在敏捷技术实践领域一直走在前沿,在TDD和单元测试领域颇有研究。他将本书分为三部分,首先分析了编写测试的目的,以及优秀测试的特征,然后是本书的核心部分,从三个角度一一阐述了测试的坏味道。此外,本书还介绍了测试替身的概念与用法,如何用另类JVM语言为Java代码编写测试,如何提高代码的可测性,以及如何加速测试和构建的速度,从而加快反馈的速度。
翻译是个耗时的差事,时间投入与经济回报不成比例。于是,有人不禁问你为什么还要坚持翻译。在我看来,既然自己从社区中获得很多养分,也就有义务将更多丰厚的知识和实践经验分享给大家。同样的原因,几年来我也一直坚持参与组织各种社区活动,回馈社区。
作为译者,因为能力水平有限,难免会有疏漏,在此恳请读者见谅,并给予批评指正。
在本书的翻译过程中得到了多位软件匠友大力协助,非常感谢:尹哲、伍斌、王洪亮(排名不分先后)。
感谢所有关心和鼓励我的人。特别是我的家人,在那些挑灯奋战的夜晚里默默地给予着支持。
今宵梦霓虹明空浩荡
残思追穹方月已西徜
前言
编写测试、学习JUnit的测试框架,这些都不难。要真正地掌握编写自动化单元测试实践,需要花大量时间在阅读并改善测试代码上。这种持续的测试重构能够尝试用不同方式来表达意图、组织测试的不同行为、用测试构建各种用到的对象——这才是一种务实的方式,用来自我学习和培养对单元测试的感觉。
这种感觉是关于哪些是优秀的单元测试,而哪些不那么优秀。有些是绝对的真理(比如完全在重复代码内容的注释就是冗余的,应该被删除),但大多数关于单元测试的知识都取决于上下文。通常意义上的优秀在特定条件下可能却很糟糕。同样,一般认为糟糕和应当避免的想法有时却是正确的做法。
原来,找到优秀方案的最好方式就是尝试一个看似可行的方法,识别该方法的问题,然后改变该方法从而消除讨厌的部分。通过重复这个过程,不断地评估和进化,最终你会找到一个可行的方案,它闻起来没那么臭。你甚至会说那是相当优秀的方式!
考虑到这种复杂性,本书采用了一种风格和结构,那就是我们不会告诉你怎么做,也不会告诉你怎么编写单元测试。相反,我打算给你一个坚实的基础,让你知道哪些是我们希望测试表现出的属性,然后给你尽可能多的例子来培养你对测试坏味道的感觉——帮你注意到测试中的不合时宜之处。
受众
本书针对想要提高单元测试编写质量的各个层次的Java程序员。虽然我们提供了附录来教给你测试框架(JUnit),但我们的主要目标是帮助已经了解单元测试的Java程序员,用其喜欢的测试框架来编写更好的单元测试。不管你已经写了多少单元测试,我们肯定你仍然可以做得更好,阅读本书或许能带你揭示一些难以言喻的想法。
路线图
本书提到了多个方面的挑战,因此需要良好的结构来支撑这些方面。深思熟虑后(源自于多次迭代中的失败尝试),我们决定将本书分为三个部分。
关于更好的测试,第一部分先介绍了我们要达到的目标,以及它们为什么是可取的。其中的三章展示了编写优秀测试的基本工具和简单指南。
第1章从自动化单元测试的价值主张开始。我们通过考虑程序员生产力的多种因素来建立价值,以及编写优秀自动化单元测试如何有助于生产力,或避免耽误我们。
第2章提高了标准,尝试定义什么是优秀的测试。该章中的属性和注意事项是第二部分的核心基础,涉及测试的可读性、可维护性和可靠性。
第3章进一步介绍测试替身,作为编写优秀测试的重要工具。我们并不是为了使用测试替身而使用,而是深思熟虑地用好它们。(它们不是你想要的银弹。)
第二部分与第一部分形成鲜明对比,把一个测试坏味道的目录摆在你面前。除了描述测试代码中的可疑模式外,我们也给出了面对这些坏味道时的尝试方案。这些章节分为三个主题:令可读性退化的坏味道、暗示着潜在维护性梦魇的坏味道,以及带来信任危机的坏味道。第二部分的许多坏味道可以归为三大章节中的任何一个,但我们尝试根据其主要影响来归类。
第4章中的坏味道,主要侧重于过分不透明的测试意图或实现。我们涉及诸如模糊的断言、不恰当的抽象层次和测试代码的信息分散。
第5章中的坏味道会导致在办公室加班,因为要针对一个小的变更而没完没了地修改某个单元测试,或者为了一个小的变更要修改数百个测试。我们谈及了代码重复、测试代码中的逻辑和阐述触及文件系统的恐怖。我们也不会让缓慢的测试从眼皮底下溜过去,因为时间就是金钱。
第6章是测试坏味道目录的最后一部分,谈及一系列关于假设的陷阱。有些假设是由于测试代码中麻烦的注释,有些则是由于未能清楚地表达自己而带来的失败和不幸。
第三部分可以称为“高级话题”。然而并非如此,因为这里的话题与第一部分和第二部分并无关联。相反,这些是Java程序员在编写测试时随时可能碰到的话题。毕竟,无论是关于单元测试类的继承关系,还是用来编写测试的编程语言,或是构建设施运行测试的方式,几乎所有关于“优秀”单元测试的内容都依赖于上下文,所以对于造成某些程序员紧迫的话题,却无法打动另外一些人,这毫不奇怪。
第7章紧接第2章,探讨什么是可测的设计。先大致阐述了有用的原则,并澄清我们其实是在寻找模块化设计,然后我们学习了基本的可测性问题,它会导致代码不可测。该章最后给出一些简单的指南,来保证我们走在可测设计的康庄大道上。
第8章抛出一个突如其来的问题,如果我们用Java之外的编程语言来编写单元测试如何?Java虚拟机允许当今的程序员采用一些另类的编程语言,并将它们与普通Java代码集成到一起。
序言
那是很久以前的事情了,而你现在看到的书与Roy的书已经大不相同了。我来解释一下。
项目一开始只是直接地从.NET翻译成Java,仅仅会为了符合技术平台、工具和读者的变化而重写一些必要之处。我完成了第1~3章,然后突然发现自己不只重写了一些段落,而是整个章节。那书不是我的调调;有时我不同意Roy的看法或者意见有偏差,有时我希望表达自己的想法,直截了当,大步前进。
最终,我决定从头开始。
很显然这不是一个翻译项目。这是全新的题目——一本帮助Java开发者改善测试的书,让人深入了解何为优秀的测试,以及避免落入各种陷阱。你仍然会在本书中以各种方式见到Roy的思想。例如,第二部分的章节标题就明显地从Roy那里借鉴而来,而第7章在很大程度上要感谢Roy的《.NET单元测试艺术》书中的相应部分。
本书是针对Java程序员的。但我并不想将想法束缚在本书中,因此即便模式目录中的所有代码例子都是用Java写的,我也尽量避免特定于语言的内容。书写优秀测试是个与语言无关的问题,即使你的大部分工作时间都花在另一种编程语言上,但是我也真心地推荐你带着思考来阅读本书。
与此同时,我不希望写成我喜欢的mock对象库或JUnit的一个教程。除了因为这些技术更新得太快以至于出版几个月就会过时,我也是希望写一本自己乐意去阅读的书。我喜欢专注的书籍,它不会强加我早就了解的一个测试框架或者用不到的mock对象库,而造成额外负担。基于这些原因,我尽量减少特定于技术的建议。虽然还是会有一些,但是我希望你知道我已经尽最大努力来减少它们了——只是用来有意义地谈论底层概念,那些概念我认为是书写、运行、维护和改善测试的基础。
我试着写了自己愿意读的一本书。我希望你也喜欢,而且最重要的是能将其中一些想法融入到你的实践中。
媒体评论
——Roger Cornejo, GlaxoSmithKline
这本书改变了我对Java开发过程的看法,强烈推荐!
——Phil Hanna, SAS Institute, Inc.
这本书阐释了书写高质量代码的常识性方法。
——Frank Crow Sr. , Progeny Systems Corp.
非常有用,即使你采用.NET编写代码。
——J. Bourgeois, Freshly Coded
如果单元测试是你的噩梦,那就来读这本书吧!
——Franco Lombardo, Molteni Informatica
书摘
通过关注对生产力的影响力,你可以扩展质量稳态。使程序员变得高效的关键正是这些已经识别出的根本原因。高产的先决条件是你足够了解你的工具,而不是持续分散你的注意力。一旦你了解了编程语言,你可以浏览其核心API。当你熟悉了问题域,就专注于根本原因——可读性、可靠性、可信赖性和测试的速度。
这也是本书剩余大部分将要围绕的内容——帮助你提高对测试代码可读性、可信赖性和可靠性的意识和感觉,并确保你能持续使用这种工作方式,以确保可维护性。
在那之前,我们来解释图1.2中的第二条曲线。
1.2.2设计潜力的曲线
假设你先写了最重要的测试——针对最常见和基本的场景,以及软件架构中的关键部位。
你的测试质量很高,你大胆地将重复都重构掉,保持测试精益且可维护。现在想象一下,你积累了如此高的测试覆盖率,唯一没测到的地方只是那些直接针对字段的访问器。平心而论,为那些地方写测试没什么价值。因此,之前的做法倾向于收益递减——你已经不能再从“仅仅”编写测试这件事中获取价值了。
这是由于我们不做的事情而造成的质量稳态。之所以这么说是因为想要达到更高的生产力,你需要换个思路去考虑测试。为了找回丢掉的潜力,你需要从编写测试中找到完全不同的价值——价值来自于创新及设计导向,而非防止回归缺陷的保护及验证导向。
总而言之,为了能同时达到两个稳态,从而完全发挥测试的潜力,你需要:
1。像生产代码一样对待你的测试代码——大胆地重构、创建和维护高质量测试,你自己要对它们有信心。
2.开始将测试作为一种设计工具,指导代码针对实际用途进行设计。
如前所述,前者造成了大多数程序员在编写测试时会不知所措,无法顾及高质量,或降低编写、维护、运行测试的成本。这也是本书的重点——编写优秀的测试。
也就是说我们不会花很多时间去讨论利用测试作为设计的方面。我只是想让你对这种动态和工作方式有个全面的了解,那我们详细说说这个话题再前进吧。
1.3测试作为设计工具
传统上,程序员编写的自动化测试被看做是质量保证工作,用于在编写的时候验证实现的正确性,以及将来代码进化的时候验证正确性。这就是将测试作为验证工具——你设想一份设计,编写代码实现,编写测试验证实现是否正确。
使用自动化测试作为设计工具将世界颠倒过来了。当你用测试设计代码时,你将典型的“设计,编码,测试”序列变换为“测试,编码,设计”。是的,就是那样。测试先于编码,并以追溯性的设计活动来得出结论。那结论性的设计活动称为重构,序列变为“测试,编码,重构”.如图1.4所示。
1.3.1测试驱动开发
TDD,如图1.5所示,是一种很有章法的编程技术,它基于一个简单的想法:在编写出能够证明代码存在的失败测试之前,不写生产代码。这也是它有时被称为测试先行编程的原因。
不止这些。先写测试,会向测试所期望的方向来驱动生产代码的设计。这会带来以下令人满意的后果:
·代码变得可用——代码的设计和API适合于你的使用场景。