版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、Unit TestIn J2EE Application,Tim_wang,PTS team 11/14/2008 9:51:11 AM,Overview,TDD Introduction,第一部分:TDD介绍 什么是TDD 为什么要使用TDD 如何使用TDD,Overview,What is TDD?,TDD是Test-Driven Development (测试驱动开发) 测试先行 持续重构,Overview,Why TDD?,TDD能够带来: 减少开发周期中的反馈 提高代码质量 保证设计质量 集中精力开发一个功能,Overview,Why TDD?,TDD为最小的逻辑单元提供了验证: 确
2、保每个方法都是可用的且已被测试过 确保及时发现出现问题的模块 添加或修改代码更容易 频繁地运行测试 迭代式递增开发 不断重构以改善设计,Overview,Why TDD?,TDD还能改善和验证设计: 以客户端的视角编写测试 为客户端提供了示例代码 更注重接口的设计 为了使测试容易,需要实现松散耦合 更少的Debug时间,Overview,Why TDD?,事物都有两面性:TDD的缺点 需要编写更多的代码,Overview,How to do TDD?,每当新增一个功能时:,编写测试,编写代码,运行测试,对代码做小的修正,完 成,通过,失败,Overview,How to do TDD?,先编写
3、测试,XP涉及两种测试:程序员测试和客户测试。 测试驱动的编程(也称为测试为先编程)最常指第一种测试,至少我使用这个术语时是这样。测试驱动的编程是让程序员测试(即单元测试重申一下,只是换用一个术语) 决定您所编写的代码。这意味着您必须在编写代码之前进行测试.测试指出您需要编写的代码,从而也决定了您要编写的代码。您只需编写足够通过测试的代码即可以不用多,也不用少。XP规则很简单:如果不进行程序员测试,则您不知道要编写什么代码,所以您不会去编写任何代码。,Overview,How to do TDD?,如何先编写测试,这里我将举一个简单的例子,让您体会一下: 假定我正在编写包含 Person 对象
4、的系统。 我希望在我问每个 Person 时,他她能告诉我其年龄(作为整数)。,Overview,How to do TDD?,即使我还没有编写一丁点代码,但也该编写测试了。“什么?”,您可能会说,“我甚至不知道在测试什么,怎么编写测试?”答案很简单,您的确知道您在测试什么,只是不知道您所了解的内容,因为您不习惯按这样的方式进行思考。这就是我的意思。您确实还没有任何代码,但您脑海中应有 Person 对象的雏形。 Person 对象上应该有一个方法,该方法可以用整数形式返回年龄。,因为我最常使用 Java 语言,所以我用JUnit来编写程序员测试。 清单 1 显示了我为 Person 对象编写
5、的 JUnit 测试:,Overview,How to do TDD?,清单 1. 用于 Person 对象的 JUnit 测试,package com.pts.testexample; import junit.framework.TestCase; public class TC_Person extends TestCase protected Person person; public TC_Person(String name) super(name); protected void setUp() throws Exception person = new Person(); pu
6、blic void testGetAge() int actual = person.getAge(); assertEquals(0, actual); protected void tearDown() throws Exception ,Overview,How to do TDD?,显然,我还没有 Person 类,所以运行该测试会出现问题 JUnit 给出了一个红条。如果可以运行,并通过测试,则会显示一个绿条。您的目标总是设法得到一个绿条。别忘了,JUnit 的座佑铭是“得到绿条,使代码干净”(有时抱怨是难免的)。,没问题。我将创建 Person 类,如清单 2 所示: 清单 2.
7、Person 类package com.pts.testexample; public class Person public int getAge() return 0; ,Overview,How to do TDD?,现在,当运行这个测试时,测试通过,应该可以看到一个绿条。 我必须从 getAge() 返回值,否则不会编译它。这里碰巧 0 最方便, 0 被认为是新的 Person 实例的缺省值,所以工作正常。再次重申, 我编写了通过测试所需的代码。 能够使 Person 具有缺省的年龄值固然很好,但这对我的系统不会有 太大帮助。 Person 需要比这更智能些。我真正所需要的是, Per
8、son 拥有其生日,并能回答其当前的年龄。这意味着 Person 对象的年龄 会随时间的推移而增长。,Overview,How to do TDD?,在进行编码前,将 testGetAge 重命名为 testGetDefaultAge (清楚地表明,我正在测试缺省的年龄),并为这个测试案例编写另一个测试方法,如清单 3 所示: 清单 3. 新的测试方法public void testGetAge() GregorianCalendar calendar = new GregorianCalendar(1971, 3, 23); person.setBirthDate(calendar.getT
9、ime(); int actual = person.getAge(); assertEquals(31, actual); 还不能编译这个测试(您注意到了其中的模式吗?),因为 Person 内没有 setBirthDate() 方法,Overview,How to do TDD?,生成的 AssertionFailedError 告诉我结果不是 31 而是 0。这个失败在 预料之中,因为我没有改变 getAge() 方法来做某些不同的事。现在仅仅编 写足够使测试通过的代码(这里有两个测试)。我必须允许年龄的缺省值为 0,但我必须计算出生于 1971 年 3 月 23 日的人的年龄。一些资深
10、程序员建议在这一点上尽可能简单,譬如检查 birthdate ,看它是否为 null 如果为 null,则返回 0,否则返回 31 然后编写另一个测试使计算更智能。一小步一小步地思考问题这种方法是很好的技术,我们要采用这种技术,当您想回到上面提到的基本规程来使自己摆脱调试惯例时,那是再好不过。但这里我想使该示例略微简单些,所以我仅仅试图通过按我所希望的方式,用 Calendar 计算年龄,使该测试通过。,Overview,当我运行测试时,我失败了,预期的结果为 31,但实际结果为 32。怎么了?唔,我知道问题一定出在刚才所写的代码中,没有进一步考虑下去。在检查完 else 子句之后,我明白我只
11、是根据年来计算年龄。这不对。我现在 31 岁,但这个月再过几天我要 32 岁了(但我写该代码时,是 3 月份),我的算法造成错误的结果。所以需要重新考虑 getAge() 。我用清单 6 中的代码段纠正了这个错误: 清单 6. 改正后的 getAge()else int yearToday = Calendar.getInstance().get(Calendar.YEAR); Calendar calendar = new GregorianCalendar(); calendar.setTime(birthdate); int birthYear = calendar.get(Calend
12、ar.YEAR); if (yearToday = birthYear) return yearToday - birthYear; else return yearToday - birthYear - 1; ,Overview,绿条!在 Person 类中有一些重复的代码,但我把它留给稍后的重构练习。欢迎替我清理该代码。您可以有信心地做这件事,因为可以运行测试来证实您没有破坏任何事物。 这个示例使您体会到了测试驱动的编程类似于什么。我只在每步编写足够让测试通过的代码。作为一种理论,这在思想倾向上是一种挑战。您必须习惯这种思想,在编写代码 之前,可以并应该编写测试。在通过所有测试之后,就完成
13、了工作。 在先编写测试时,必须习惯故意只看眼前。清单 6 中的示例是一个十分简单的情形。即使最简单的编程问题,在实际当中通常要更复杂。这种方法有助于将问题分解成更可管理的部分,但您最终仍可能遇到一些复杂 的令人头疼的问题。在那些情况下,必须使自己不要考虑太远,不要假定它的“普适性”有多高,也不要假定这种方法能处理某些尚未遇到的情形。仅仅编写测试, 使它通过。您需要采取一些较小的步骤,然后编写迫使您要采取更多步骤的测试。请记住,您正在测试代码的存在性,如果您以较小的步骤来编写代码,那您就做对了。,Overview,为什么应该先编写测试 也许您不认为先编写测试是一个好主意。它看上去似乎很奇怪,或者
14、也许似乎没有必要。我常从富有经验的程序员那听到第二种原因。这些程序员很聪明,他们具有 许多经验,他们说不需要先编写测试,因为他们知道自己在做什么。我能领会,但我怀疑他们存在一个隐式的假定:他们没能领会先编写测试。恕我难以苟同。事实 上,我认为采用先编写测试方法有三个原因: 学习 新问题 信心 先编写测试到后面再执行这些测试是较佳的学习方式。它使您能将精力集中在所编写代码的接口部分。在编写测试时,您假设正在使用的类已经存在,然后按照您希望在系统其余部分中使用的方式来 使用该类。稍后,当您忘记如何使用该类时,可以查看测试,看一个非常具体的示例。这是学习的很好方式。 关于先编写测试最有趣的事情之一是,它有助于发现新问题。您正在使创建之中的系统“成长”起来。如果您正在使用 XP,则没有预先设计整个事情 而是一边开发一边设计。在您先编写测试并通过测试这个过程中,您正在让代码告诉您它想要做什么,以及会成为什么。如果仅仅着手编码工作,则您完全按照您的 设想来行事了。越晚做决定,则越有可能发现新问题和新动向,这些可使您的系统更完善。 但是,我所喜欢的先编写测试的好处是让这些测试在稍后执行。在我先编写测试时,我有许多奇异的逻辑。我可能没有涵盖代码 的方方面面,但会包括其中许多方面。在任何情况下,我会有一套测试,这套测试比我曾参与过
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025渭南合阳县煤炭事务中心招聘(12人)笔试参考题库附带答案详解
- 2025浙江湖州市检验检测中心公开招聘工作人员1人笔试参考题库附带答案详解
- 2026及未来5年中国80克双胶纸市场数据分析及竞争策略研究报告
- 浙江国企招聘2025浙江交投中碳环境科技有限公司招聘20人笔试历年难易错考点试卷带答案解析
- 通化市2025年吉林通化市事业单位招聘基层治理专干(162人)笔试历年参考题库典型考点附带答案详解
- 福州市2025福建福州市知识产权发展保护中心招聘工作人员1人笔试历年参考题库典型考点附带答案详解
- 桐城市2025安徽安庆桐城市事业单位公开招聘工作人员58人笔试历年参考题库典型考点附带答案详解
- 广西壮族自治区2025广西河池市罗城仫佬族自治县实施乡村振兴战略指挥部招聘工作人员5人公笔试历年参考题库典型考点附带答案详解
- AI在轻工工程中的应用
- 2026糖尿病营养不良饮食干预课件
- 医疗领域国家安全知识讲座
- 自行车的力学知识研究报告
- 半导体光电子器件PPT完整全套教学课件
- 七年级期中考试家长会课件
- 糖尿病的中医分类与辩证施治
- 造价咨询投标服务方案
- 英语 Unit9Wherewillyougo的教学反思
- GB/T 3292.1-2008纺织品纱线条干不匀试验方法第1部分:电容法
- 突发环境事件应急隐患排查治理制度
- 第6章双离合器变速器结构与原理课件
- 新版抗拔桩裂缝及强度验算计算表格(自动版)
评论
0/150
提交评论