1. 单元测试的目的
一个单元测试从整个系统中单独检验产品程序代码的『一个单元』并检查其得到的结果是否是预期的。要测试的『一个单元』其大小是依据一组连贯的功能的大小及介于一个类别及一个包(package)之间实际上的变化 (varies)。其目的是在整合程序代码到系统的其余部分之前先测试以便找出程序代码中的臭虫(bugs)。Junit等支持在Java程序代码中撰写单元测试。
在整合之前于系统其它部分隔离起来抓虫的理由是因为那是比较容易的找到臭虫(亦即比较快且便宜)及比较容易修正问题(并显示其解决方式是可行的)。
单元测试对于在初始整合一小部分程序代码以及整合其余的改变之前提供了一些利益。如果有人需要变动现有的程序代码,事实上单元测试仍然可以让他对于其后的程序代码更有信心;即他的改变不会破坏任何东西。愈好的单元测试让人愈有信心--理想上测试必须在加入的新功能前也随之更新。
2. 谁来撰写单元测试及何时撰写单元测试
程序代码测试可能是非常乏味的,尤其是测试别人的程序,而当你是一个程序设计师的时候尤甚。但程序设计师喜欢撰写程序,因此为什么不让程序设计师撰写一些程序可以作为测试之用呢?
当单元测试正确的实作可以帮助程序设计师变的更有生产力,而同时提升开发程序代码的品质。有一点你必须了解的是单元测试应该是开发程序的一部份是很重要的;而且程序代码的设计必须是可以测试的。目前的趋势是在撰写程序代码之前要先撰写单元测试,并且把焦点放在Java类别的接口及行为上。
先写测试,再写代码的好处:
从技术上强制设计师先考虑一个类的功能,也是这个类提供给外部的接口,而不至于太早陷入它的细节。这是面向对象提倡的一种设计原则。
好的测试其实是一个好的文档,这个类使用者往往可以通过查看这个类的测试代码了解它的功能。特别的,如果你拿到别人的一个程序,对他写测试是好的了解这个程序的功能的方法。 xp的原则是 make it simple,不是很推荐另外写文档,因为项目在开发过程中往往处于变动中,如果在早期写文档,以后代码变动后还得同步文档,多了一个工作,而且由于项目时间紧往往文档写的不全或与代码不一致,与其这样,不如不写。而如果在项目结束后再写文档,开发人员往往已经忘记当时写代码时的种种考虑,况且有下一个项目的压力,管理人员也不愿意再为旧的项目写文档。导致以后维护的问题
没有人能保证需求不变动,以往项目往往对需求的变动大为头疼,害怕这个改动会带来其它地方的错误。为此,除了设计好的结构以分割项目外(松耦合),但如果有了测试,并已经建立了一个好的测试框架,对于需求的变动,修改完代码后,只要重新运行测试代码,如果测试通过,也保证了修改的成功,如果测试中出现错误,也会马上发现错在哪里。修改相应的部分,再运行测试,直至测试完全通过。
软件公司里往往存在开发部门和测试部门之间的矛盾:由于开发和测试分为两个部门,多了一层沟通的成本和时间,沟通往往会产生错误的发生。而且极易形成一个怪圈:开发人员为了赶任务,写了烂烂的代码,把它扔给测试人员,然后写其它的任务,测试当然是失败的,又把代码拿回去重写,测试成了一个很头疼的问题。这种怪圈的根源是责任不清,根据 xp 中的规定:写这个代码的人必须为自己的代码写测试,而且只有测试通过,才算完成这个任务(这里的测试包括所有的测试,如果测试时发现由于你的程序导致别的组的测试失败,你有责任通知相关人员修改直至集成测试通过),这样可以避免这类问题的发生。
简而言之,如果程序设计师要写一段代码:
先用 junit 写测试,然后再写代码;
写完代码,运行测试,如果测试失败,
修改代码,运行测试,直到测试成功。
如果以后对程序进行修改,优化 ( refactoring ),只要再运行测试代码。如果所有的测试都成功,则代码修改完成。
3. 单元测试与Java Team开发的结合
Java下的team开发,一般采用cvs(版本控制) + ant(项目管理) + junit(单元测试、集成测试)的模式:
每天早上上班,每个开发人员从 cvs server 获取一个整个项目的工作拷贝。
拿到自己的任务,先用 junit 写的任务的测试代码。
然后写任务的代码,运行测试(单元测试),直到测试通过。
任务完成在下班前一两个小时,各个开发人员把任务提交到cvs server。
然后由主管对整个项目运行自动测试(集成测试),哪个测试出错,找相关人员修改,直到所有测试通过。下班。。。
4. 测试控制工具中要有甚么?
无论谁来撰写单元测试或何时撰写单元测试,我们的焦点应该放在检验程序代码;主要是在于产生错误的风险。如果设计文件包含被测试对象的使用情节;便可成为好的测试来源。不管如何,这些情节写得不是很明确;因为这些情节实际上是以设计观点所写的--因此适当的测试应该有对等的情节,换句话说,也是测试设计应该尽可能的包含用户实际使用程序时可能产生的动作或者过程。
另一个测试案例好的来源是在整合后从产品程序代码当中找到的问题,维修问题的处理方式往往值得封装成为测试案例。
5. 为什么要使用Junit等工具呢?
前面的论述说明为什么我们需要测试控制工具,但为什么我们使用Junit这些工具呢?
首先,它们是完全Free的啦!。
第二点,使用方便。
l 在你提升程序代码的品质时JUnit测试仍允许你更快速的撰写程序
那听起来似乎不是很直觉,但那是事实。当你使用JUnit撰写测试,你将花更少的时间除虫,同时对你程序代码的改变更 俱有信心。这个信心让你更积极重整程序代码并增加新的功能。没有测试,对于重整及增加新功能你会变得没有信心;因为你不知道有甚么东西会破坏产出的结果。采用一个综合的测试系列,你可以在改变程序代码之后快速的执行多个测试并对于你的变动并未破坏任何东西感到有信心。在执行测试时如果发现臭虫,原始码仍然清楚的在你脑中,因此很容易找到臭虫。在JUnit中撰写的测试帮助你以一种极 大(extreme)的步伐撰写程序及快速的找出缺点。