测试驱动开发(中文完整版-带书签)

所需积分/C币:50 2016-08-30 15:51:54 6.57MB PDF
91
收藏 收藏
举报

测试驱动开发(中文完整版-带书签)
收集参数 140 单例模式( Singleton) 要。卡·带·省··是要音音非··非非p自音·香看甲告中;4垂非自身音自非·自普·自音垂· 141 第31章重构 .142 调和差异( Reconcile differences) 142 隔离变化( Isolate Change) 备香。。 击由·鲁昏··。b 143 数据迁移( Migrate Data) 143 提取方法( Extract Method) ………145 内联方法( Inline method) 145 提取接口( Extract Interface).146 转移方法( Move method) 147 方法对象( Method object) ··‘·‘··········· 暴鲁垂暴4鲁自 148 添加参数( Add Parameter)… 149 在第一部分, 把方法中的参数转变为构造函数中的参数….......1249 外,它们纯粹是 第32章掌握TDD 50 Development, TEa3 (1)快速新增 附录A影响图 日。看非。.甲。。击自击。· 161 (2)运行所有翻 反馈 162 (3)做一些小 附录B斐波纳契数列 (4)运行所有 (5)重构( 你可能产生的 每个测 为了使 多长时闯 重构是幽 第 140 141 142 142 143 143 第一部分 145 145 资金实例 148 149 在第一部分,我们将会开发一个典型的完全由测试驱动的代码模型(那些跑题的部分除 149 外,它们纯粹是出于教学的需要)。我的目标是让你迅速了解测试驱动开发( Test-Driven Development,TDD)的过程,这个过程大体上可以归纳为以下几个步骤: 150 1)快速新增一个测试。 (2)运行所有的测试,发现最新的测试不能通过 162 (3)做一些小小的改动。 (4)运行所有的测试,并且全部通过 (5)重构( refactor)代码,以消除重复设计( duplication),优化设计结构 你可能产生的疑问包括 每个测试是怎样覆盖一小部分新增功能的 为了使新测试运行通过,我们所做的改动有多么少、方法有多么笨 多长时间运行一遍测试 重构是由多少微小的步骤组成的 多币种资金 我们就从Ward在 Wy Cash系统中创建的多币种资金( multi-currency money)这个对象(参 见“导言”)开始谈起吧。假设我们有这样的一个报表: 票据 股份 股价 合计 IBM 1000 25 25000 GE 400 100 40000 65000 为了使其变成一个多币种的报表,我们需要加上币种单位: 票据 股份 股价 合计 IBM 1000 25美元 25000美元 Novartis 400 150瑞士法郎 60000瑞士法郎 合计 65000美元 当然,我们还需要为此指定汇率( exchange rate): 源币种 兑换币种 汇率 瑞士法郎 美元 当蹦士法郎与美元的兑换率为21的时候5美元+10瑞士法郎=1美元 美元250美元 我们要怎么做才能产生上面经过修订的报表呢?或者说,哪些测试一旦通过,就能够说明 目前我们信赖的这些代码可以正确地计算出报表了呢? 在假设已经给定汇率的情况下,要能对两种不同币种的金额相加,并将结果转换为某 种币种 要能将某一金额(每股股价)与某一个数(股数)相乘,并得到一个总金额。 第1章 为此,我们将建立一个计划清单(to- do list)以提醒我们需要做哪些事情,它将使我们始 没有构造函 终保持注意力集中,同时它也可以告诉我们什么时候可以完工。当我们开始某一项工作时,我 没有 times(int 们用粗体来表示它,就像这样。当我们完成某项工作时,我们将其划去,就像这样。如果我 没有 amount 们想起其他要做的测试,就将其加入清单。 让我们逐一改正 正如前面的计划清单所讲的一样,我们就从实现乘法这个功能开始。那么,我们首先需要类来去掉一个错误: 建立什么对象呢?什么对象也不需要。记住,我们不是从建立对象开始,而是从测试开始。(我 o业ar 一直都在提醒自己注意这个问题,希望你也能时刻记住提醒自己。) class Dollar 既然如此,那么我们首先应该进行什么测试呢?清单中的第一个测试看起来很复杂,我们 个错误已经解 需要从比较简单的开始。第二个测试不过是实现乘法功能而已,能难到哪儿去呢?我们就从它译通过,它不必实现任 开始吧。 在编写测试的时候,我们总是为我们的操作设想最完美的接口( interface)。我们总是告诉 Dollar(int amount)[ 自己这些操作在外界看来应该是个什么样子,尽管很多时候我们的设想并不能化为现实,最好 是从一种尽可能优秀的应用编程接口( application program interface,API)开始,然后再倒着 还有两个错误。我 进行设计,这要比从一开始就把一切都搞得很复杂、拙劣而“现实”好 程序通过的最少的工作 下面是一个关于乘法功能的简单实例: D olr public void testMultiplicationo i void times(int multipl Dollar five= new Dollar(S) five times(2) assertEquals(10, five, amount) 仅剩下一个错误。 Dollar [我知道,我知道!这段代码有很多问题:公共域问题,副作用问题,货币金额用整数来 Int anount 表示的问题,等等。别急,一步一步来。我们将这些毛病记录下来,然后继续前进。显然,测 好了,现在我们可 试没有通过,但是我们希望测试能够尽快到达可运行状态( green bar)0 当瑞士法郎与美元的兑换率为21的时候,5美元小10瑞土法郎=10美元 5美元2Q 将“ amonEt”定义为私有 器验物 Doa类有副作用吗? 钱数必颏为整数? 我们刚才键入的测试程序甚至还不能通过编译。[我会在后边讲测试框架(ttng framework) JUnit的时候解释在什么地方键入以及怎样将其键入。]修改这样的测试非常简单 即便是编译后也无法运行,但为了使其能够编译通过,我们至少要做哪些工作呢?我们存在以 下四个编译错误: 没有Dola类 ① Junit测试工具运行测试时,如果测试全部运行通过,那么状态条是绿色的;如果存在没有通过的测试,那么状态条就是红色的。 本书作者大量使用包含geen或ted的字句,我们以后统-将其译作测试运行通过或没有通过。一译者注 多币种资金 些事情,它将使我们始 没有构造函数 开始某一项工怍作时,我 没有tme(int)方法 去,就像这样。如果我 没有 amount域 让我们逐一改正(我总是在寻找某种度量进度的数值化方法)。我们可以通过定义 Dollar 那么,我们首先需要 类来去掉一个错误 而是从测试开始。(我 class Dollar 试看起来很复杂,我们 个错误已经解决,还有三个。现在我们需要一个构造函数,但是单单为了让测试能够编 哪儿去呢?我们就从它 译通过,它不必实现任何功能 Dollar nterface)。我们总是告诉 Dollar(int amount)i 眼并不能化为现实,最好 API)开始,然后再倒着 还有两个错误。我们需要 timeso的存根实现( stub implementation)。同样仅做可以使测试 好 程序通过的最少的工作 oar void times ( int multiplier)[ 仅剩下一个错误。最后,我们需要一个 amount域: Dollar 题,货币金额用整数来 int amounta 然后继续前进。显然,测 好了,现在我们可以运行测试程序,结果如图1-1所示,失败了 边讲测试框架( testing 改这样的测试非常简单。 哪些工作呢?我们存在以 framework AssertionFailed Error: expected *10>but waa 0> MoneyMoney Test testmultipilcation MoneyTestjava: 18) 过的测试,那么状态条就是红色的。 图1-1虽然测试失败,但有进步 过。一—译者注 第1章 可以看出测试程序没有运行通过( red bar)。我们在测试框架(在该例中为 JUnit)中运行 (4)运行所有 了这个作为开篇所编写的一小段代码,可以发现,尽管我们希望结果是“10”,事实上却很不 (5)重构代码以 幸,我们看到的结果是“0”。 没有关系,失败也是一种进步。我们已经对这次失败有了一个具体的衡量,这要比只是模 依赖关系 模糊糊地知道自己要失败的好。我们要解决的编程问题已经由原来的“实现多币种”转化为“让 Steve fre 这个测试程序能够工作,然后让剩下的测试程序也能够工作”。问题已经比以前简单多了,要 设计的概念我作 考虑问题的范围也小了很多。而且,我们完全可以让这个测试程序工作起来。 码与测试程序之 你也许不喜欢这个解决方案,但是现在的目的不是获得最完美的解决方案,而是让这个测 的目标是编写另 试程序可以运行。我们将在做出理想的产品之前做出点牺牲 不可能的 下面是我所能想到的可以让测试程序通过的最小改动: 依赖关系是 Dollar 实现散布在整个 ant amount 赖于某家数据库 图1-2显示了测试程序再次运行后的结果。现在测试程序运行通过,可喜可贺! 如果问题 不过不要高兴得太早,致力于电脑编程的男孩女孩们,这一轮的工作还没完成呢!世界上 辑上的重复设训 恐怕很难找到几个输入可以让这个功能有限、风格很差、近乎弱智的测试程序运行通过。所以, 抽象出逻辑上献 我们在继续前进之前要把它一般化。记注,这一轮工作由下列的环节组成: 与现实生活 其他更恶劣的形 测试驱动开发第 最 aMone test 通过一处且仅悦 (4)项 段代码之间,但是在 如果我们这样写会怎 Dollar int amount5* 2 这个10必然有 儿的5与2处于两 复 我们无法只通划 而将这个过程移至t 图1-2测试程序运行 Int amount (1)新增一个测试 d times〔 int ruIt (2)运行所有的测试程序并失败。 amount5* 2 (3)做一些小小的改动。 多币种资金 该例中为 JUnit)中运行 (4)运行所有的测试程序,并且全部通过 是“10”,事实上却很不 (5)重构代码以消除重复设计,优化设计结构 本的衡量,这要比只是模 依赖关系( dependency)与重复设计( duplication) 实现多币种”转化为“让 Steve freeman指出:测试程序与代码所存在的问题不在于重复设计(关于重复 经比以前简单多了,要 设计的概念我们还没有提到过,但我将在这段闲话说完后尽快向你解释),而在子代 作起来。 码与测试程序之间的依赖关系——你不可能只改动其中一个而不改动另外一个。我们 解决方案,而是让这个测 的目标是编写另外一个对我们有用的测试而不必改动代码,而这对于当前实现而言是 不可能的 依赖关系是各种规模的软件开发中的关键问题。如果你让一家厂商的SQL具体 实现散布在整个产品代码中,而又决定换成另一家厂商,那么就会发现,你的代码依 赖于某家数据库厂商,你在不修改代码的情况下无法改变数据库 过,可喜可贺! 如果问题出在依赖关系上,那么其表现就是重复设计。重复设计通常表现为逻 工作还没完成呢!世界上 辑上的重复设计—相同的表达式在代码的多个地方出现。利用各种对象可以很好地 试程序运行通过。所以, 抽象出逻辑上的重复设计 组成: 与现实生活中的大多数问题不同,在现实生活中,消除某种症状往往使问题以 其他更恶劣的形式重新表现岀来,消除程序中的重复设计就是消除依赖关系,这就是 测试驱动开发第二条规则的由来。只有在编写下一个测试之前消除现有的重复设计, 通过一处且仅仅一处改动即可让下一个测试运行通过的可能性才最大 (1)~(4)项我们都已运行过了。那么什么地方有重复设计呢?通常重复设计存在于两 段代码之间,但是在这儿重复设计却存在于测试中的数据与代码中的数据之间。你看到了吗? 如果我们这样写会怎样呢 Dollar int amount=5* 2 这个10必然有它的来历,我们只顾在大脑中快速地做乘法以至于将这点忽略了。在这 儿的5与2处于两个不同的地方,所以依照规则,在我们继续之前必须亳不留情地消除重 复 我们无法只通过一步就消除5和2。既然如此,可以不在对象初始化时给 amount赋值, 而将这个过程移至tmes(O方法中 Dollar Int amount: void times(int multiplier)[ amount=5* 2 8 第1章 测试仍然通过,测试程序保持在可运行状态。 暂时忽略JUni 这样的软件开发步伐对于你来说是否太小了?记住,测试驱动开发并非一定要采取这样 通过建立存根 小步一小步的开发过程,而是要培养你将软件开发化为这样的一小步一小步的开发任务的能 通过一些另类 力。我日复一日都以这样小的步伐进行开发吗?当然不是。但是当情况变得有些棘手时,我很 逐渐使工作代 高兴我有这样的能力。选择一个简单的例子一步一步来尝试,来学习。如果你可以将软件开发 将新工作逐步 分成一个个粒度比较小的开发任务,那么你自然可以将它分得大小适当。但是如果你仅仅采用 较大的步伐进行开发,那么你根本不会知道较小的步伐是否合适。 言归正传。我们刚才谈到哪儿了?对,谈到如何消除测试代码和工作代码之间的重复 我们可以从哪儿得到一个5呢?这是传给构造函数的值,所以我们用 amount变量来保存 Dollar Dollar(int amount)( this, amount= amount 然后我们就可以在tmeO函数中使用它: Dollar void times (int multiplier)i amount= anount 2 参数“ multiplier”的值是2,所以我们可以用这个参数来代替这个常量 Dollar void times(int multiplier)i amount= amount multiplier; 为了证明我们精通Java的语法,我们将使用*=操作符(这确实削减了重复内容) Dollar void times(int multiplier)[ anount=靦 tipler; 当通士法部与类先的先换为2的时5美元10氟法1美玩 餐“义为有 钱数必须为整数?8 DoMm类有副作用吗? 现在可以说第一个测试已经完成了,下一步我们将解决那些奇怪的副作用问题。在此之前 让我们回顾一下,我们做了以下的工作 创建一个清单,列出我们所知道的需要让其运行通过的测试 通过一小段代码说明我们希望看到怎样的一种操作

...展开详情
试读 127P 测试驱动开发(中文完整版-带书签)
立即下载 低至0.43元/次 身份认证VIP会员低至7折
一个资源只可评论一次,评论内容不能少于5个字
逆水击澜 原来这书也只有100多页,1天就能读完,谢谢分享!
2017-05-29
回复
iwin32 是真的带目录完整版,谢谢。
2017-05-20
回复
您会向同学/朋友/同事推荐我们的CSDN下载吗?
谢谢参与!您的真实评价是我们改进的动力~
  • 领英

    绑定领英第三方账户获取
  • GitHub

    绑定GitHub第三方账户获取
  • 脉脉勋章

    绑定脉脉第三方账户获得
  • 签到达人

    累计签到获取,不积跬步,无以至千里,继续坚持!
  • 分享精英

    成功上传11个资源即可获取
关注 私信
上传资源赚积分or赚钱
最新推荐
测试驱动开发(中文完整版-带书签) 50积分/C币 立即下载
1/127
测试驱动开发(中文完整版-带书签)第1页
测试驱动开发(中文完整版-带书签)第2页
测试驱动开发(中文完整版-带书签)第3页
测试驱动开发(中文完整版-带书签)第4页
测试驱动开发(中文完整版-带书签)第5页
测试驱动开发(中文完整版-带书签)第6页
测试驱动开发(中文完整版-带书签)第7页
测试驱动开发(中文完整版-带书签)第8页
测试驱动开发(中文完整版-带书签)第9页
测试驱动开发(中文完整版-带书签)第10页
测试驱动开发(中文完整版-带书签)第11页
测试驱动开发(中文完整版-带书签)第12页
测试驱动开发(中文完整版-带书签)第13页
测试驱动开发(中文完整版-带书签)第14页
测试驱动开发(中文完整版-带书签)第15页
测试驱动开发(中文完整版-带书签)第16页
测试驱动开发(中文完整版-带书签)第17页
测试驱动开发(中文完整版-带书签)第18页
测试驱动开发(中文完整版-带书签)第19页
测试驱动开发(中文完整版-带书签)第20页

试读结束, 可继续阅读

50积分/C币 立即下载 >