写单元测试的好处(转)
许多开发者都有个习惯,常常不乐意去写个简单的单元测试程序来验证自己的代码。对自己的程序一直非常有自信,或存在侥幸心理每次运行通过后就直接扔给测试组测试了。然而每次测试组的BUG提交过来后就会发现自己的程序还存在许多没有想到的漏洞。但是每次修改好BUG以后还是怀着侥幸心理,认为这次不会有bug了。然后又一次自信地提交,结果又败了。因为这样反复几次后。开发者花在找BUG和修复BUG的这些时间加起来已经比他开发这个模块花的时间还要多了。虽然项目经理已经预留了修改BUG和单元测试的时间。但是开发者却习惯性地在写好代码后就认为任务完成了。然后等问题出来了bug改了很多次还是修复不了的时候才和项目经理说“我碰到预想不到的问题,可能要延期发布我的代码“。如果这个项目不可延期,痛苦的加班就无法避免了。
为什么有这么多的BUG开发者却没发现呢。其实开发者是人又不是机器。人非圣贤孰能无过。BUG是不可避免的,只是每次在修复一个BUG之前基本上无法知道这个BUG是哪段代码引起。每次定位BUG可能会耗去你一个小时还是一天,这还要取决于你的水平了。但是如果你的每段核心程序都有单元测试代码。你将不需要靠你的经验去判断或猜测BUG是由哪段程序引起。你只要运行你的单元测试方法。通过简单判断测试方法的结果就可以轻松定位BUG了。所以从表面上看,为每个单元程序都编写测试代码似乎是增加了工作量,但是其实这些代码不仅为你织起了一张保护网,而且还可以帮助你快速定位错误从而使你大大减少修复BUG的时间。而且这还有利你的身体健康,你将不会因为找不出BUG而痛苦不已,也将不用废寝忘食地加班了。而且项目的进度也将尽在掌握。
其实单元测试不仅能保证项目进度还能优化你的设计。有些开发者会说,写单元测试代码太费劲了,比写业务代码还麻烦。可是如果强迫开发者必须写单元测试代码的时候。聪明且又想‘偷懒’的开发人员为了将来可以更方便地编写测试代码。唯一的办法就是通过优化设计,尽可能得将业务代码设计成更容易测试的代码。慢慢地开发者就会发现。自己设计的程序耦合度也越来越低。每个单元程序的输入输出,业务内容和异常情况都会尽可能变得简单。最后发现自己的编程习惯和设计能力也越来越老练了。
其实容易测试的代码基本上可以和设计良好的代码划等号。因为一个单元测试用例其实就是一个单元的最早用户。容易使用显然意味着良好的设计。
有着良好设计的项目一直是很注重代码重用的。代码重用的好处在这里就不多说了。但是要做到代码重用首先要保证被重用的单元程序必须是个非常优秀的程序,除了良好的设计,还要有详细的文档。另外最重要的其实是单元测试代码。不知道大家有没有这样的经历?当大家不清楚一个API 函数如何使用而去寻找文档的帮助时,往往会跳过大段的英文说明而去直接看文档中提供的样例程序,然后在自己的程序中依葫芦画瓢调用这个函数。那么,您有没有意识到,被重用的代码如果有了单元测试代码。你的测试代码就可以成为这个函数最好的API 了。
单元测试代码还可以通过简单的事务回滚功能在生产环境上做基于真实数据的测试而不用担心会产生不必要的数据。利用这样的测试代码我们可以在发布程序后check 刚才的发布是否成功。以往发布的时候我们经常会碰到一种比较尴尬的情况,当我们将程序发布到正式环境上后,我们每个人心里一直还是有点后顾之忧。因为我们不能在正式环境上运行我们的程序,只能被动地等待客户操作过后才知道发布的程序是否正常。这种情况让我们非常被动,如果运气好可能不出什么问题,可是一旦客户在正式环境上发现报了个系统异常之类的错误或者出现错误数据,那就后果很严重了,这将影响到产品的声誉,显然这样也是很没面子事。如果我们运行过单元测试代码,万一有问题我们就可以主动的发现并且修改后重新发布。而其有时候就算有问题也可能是一些比较低级的错误,或者可能是发布问题造成。基本上很快就能解决掉!这样我们不就高枕无忧了吗!
很多研究结果表明,bug发现的越晚,修改它所需要的成本就越高,因此从成本角度来看,应该尽可能早地查找和修改bug。或许有人会有异议?程序员把bug全找出来了,测试组干嘛?其实测试组进行的是集成测试,这样的测试无法全面的考虑到每个单元被调用时用的各种输入参数。就像一辆汽车,对每个零件进行测试是必须的。对组装好的汽车进行测试是无法代替每个零件的单独测试。或许对组装好的汽车进行测试可以发现某些零部件的问题。但是这个时候发现了问题就需要把汽车拆了换零件再装上。造成的成本可想而知。
重视单元测试后你将会发现单元测试带来的好处远远不止这些。目前java下的team 开发采用cvs(版本控制) + ant(项目管理) + junit(集成测试) 的模式时,通过对ant的配置,可以很简单地实现测试自动化。在所有的敏捷软件开发方法中,XP(Extreme Programming极限编程,一种轻量级的、灵巧的软件开发方法)是目前应用最为广泛的一种, 在 XP 中推崇的Test First Design的实现已经有了现成的开发手段:“ 用Junit写测试代码,写实现代码,运行测试,测试失败,修改实现代码,再运行测试,直到测试成功。以后对代码的修改和优化,运行测试成功,则修改成功。” 等到开发者习惯了这样的开发手段后,带给开发者将是一种享受!