也谈单元测试

上一篇 / 下一篇  2009-03-25 09:20:09 / 个人分类:测试随想

也谈单元测试

Founding测试工作

引子

一般的业界认为,80%的缺陷将会在单元测试阶段(Unit Test)被发现并解决,而系统集成测试(SIT)只能发现总缺陷数的15%,最终在客户验收测试(UAT)只会发现少于5%的缺陷,而这3个阶段修改的成本也是成几何级数增长,比如在单元测试阶段花1块钱能修复的缺陷,到了系统集成测试阶段就需要至少10块钱,因为经过测试人员的发现,开发人员确认修复,最后测试人员的关闭,经历了一系列的流程,成本自然会很高,至于到了客户验收测试的时候,除去了修改缺陷,内部回测以外,大量缺陷往往会遗失客户的信心,危害巨大.于是本文将着力介绍单元测试,希望对广大开发人员有所帮助.

 

关键字

单元测试,系统集成测试,用户接收测试

 

单元测试的定义

  单元测试(模块测试)是开发者编写的一小段代码,用于检验被测代码的一个很小的、很明确的功能是否正确。通常而言,一个单元测试是用于判断某个特定条件(或者场景)下某个特定函数的行为。例如,你可能把在出生日期的输入框中输入我爱方正”,那么我们的程序需要截获这样的异常,并在页面给与客户友好的提示信息。

  单元测试通常是由程序员自己来完成,最终受益的也是程序员自己。可以这么说,程序员有责任编写功能代码,同时也就有责任为自己的代码编写单元测试。执行单元测试,就是为了证明这段代码的行为和我们期望的一致。

  工厂在组装一台电视机之前,会对每个元件都进行测试,这,就是单元测试。

  其实我们每天都在做单元测试。你写了一个函数,除了极简单的外,总是要执行一下,看看功能是否正常,有时还要想办法输出些数据,如弹出信息窗口什么的,这,也是单元测试,我们把这种单元测试称为临时单元测试。只进行了临时单元测试的软件,针对代码的测试很不完整,代码覆盖率要超过70%都很困难,未覆盖的代码可能遗留大量的细小的错误,这些错误还会互相影响,当BUG暴露出来的时候难于调试,大幅度提高后期测试和维护成本,也降低了开发商的竞争力。可以说,进行充分的单元测试,是提高软件质量,降低开发成本的必由之路。

  对于程序员来说,如果养成了对自己写的代码进行单元测试的习惯,不但可以写出高质量的代码,而且还能提高编程水平。

 

为什么要使用单元测试

  我们编写代码时,一定会反复调试保证它能够编译通过。如果是编译没有通过的代码,没有任何人会愿意交付给自己的老板。但代码通过编译,只是说明了它的语法正确;我们却无法保证它的语义也一定正确,没有任何人可以轻易承诺这段代码的行为一定是正确的。

  幸运,单元测试会为我们的承诺做保证。编写单元测试就是用来验证这段代码的行为是否与我们期望的一致。有了单元测试,我们可以自信的交付自己的代码,而没有任何的后顾之忧。

  什么时候测试?单元测试越早越好,早到什么程度?XP开发理论讲究TDD,即测试驱动开发,先编写测试代码,再进行开发。在实际的工作中,可以不必过分强调先什么后什么,重要的是高效和感觉舒适。从我们的经验来看,先编写产品函数的框架,然后编写测试函数,针对产品函数的功能编写测试用例,然后编写产品函数的代码,每写一个功能点都运行测试,随时补充测试用例。所谓先编写产品函数的框架,是指先编写函数空的实现,有返回值的随便返回一个值,编译通过后再编写测试代码,这时,函数名、参数表、返回类型都应该确定下来了,所编写的测试代码以后需修改的可能性比较小。

  由谁测试?单元测试与其他测试不同,单元测试可看作是编码工作的一部分,应该由程序员完成,也就是说,经过了单元测试的代码才是已完成的代码,提交产品代码时也要同时提交测试代码。测试部门可以作一定程度的审核。

  

  单元测试不仅仅是作为无错编码一种辅助手段在一次性的开发过程中使用,单元测试必须是可重复的,无论是在软件修改,或是移植到新的运行环境的过程中。因此,所有的测试都必须在整个软件系统的生命周期中进行维护。

  经常与单元测试联系起来的另外一些开发活动包括代码走读(Code review),静态分析(Static analysis)和动态分析(Dynamic analysis)。静态分析就是对软件的源代码进行研读,查找错误或收集一些度量数据,并不需要对代码进行编译和执行。动态分析就是通过观察软件运行时的动作,来提供执行跟踪,时间分析,以及测试覆盖度方面的信息。

现状分析

  工作中,笔者也遇到了很多开发人员会有一些理由来证明可以不做单元测试,下面罗列了一部分,和大家分享.

  1编写单元测试太花时间了。

  我们知道,在开发时越早发现BUG,就能节省更多的时间,降低更多的风险。

  如果你仍然认为在编写产品代码的时候,还是没有时间编写测试代码,那么请先考虑下面这些问题:

  1)、对于所编写的代码,你在调试上面花了多少时间。

  2)、对于以前你自认为正确的代码,而实际上这些代码却存在重大的bug,你花了多少时间在重新确认这些代码上面。

  3)、对于一个别人报告的bug,你花了多少时间才找出导致这个bug的源码位置。

  回答完这些问题,请你一定不再以太花时间作为拒绝单元测试的借口。

  2运行测试的时间太长了。

  合适的测试是不会让这种情况发生的。实际上,大多数测试的执行都是非常快的,因此你在几秒之内就可以运行成千上万个测试。但是有时某些测试会花费很长的时间。这时,需要把这些耗时的测试和其他测试分开。通常可以每天运行这种测试一次,或者几天一次。

  3测试代码并不是我的工作。

  你的工作就是保证代码能够正确的完成你的行为,恰恰相反,测试代码正是你不可缺少的工作。

  4我并不清楚代码的行为,所以也就无从测试。

  如果你实在不清楚代码的行为,那么估计现在并不是编码的时候。如果你并不知道代码的行为,那么你又如何知道你编写的代码是正确的呢?

  5但是这些代码都能够编译通过。

  我们前面已经说过,代码通过编译只是验证它的语法通过。但并不能保证它的行为就一定正确。

  6公司请我来是为了写代码,而不是写测试。

  公司付给你薪水是为了让你编写产品代码,而单元测试大体上是一个工具,是一个和编辑器、开发环境、编译器等处于同一位置的工具。

  7如果我让测试员或者QAQuality Assurance)人员没有工作,那么我会觉得很内疚。

  你并不需要担心这些。请记住,我们在此只是谈论单元测试,而它只是一种针对源码的、低层次的,为程序员而设计的测试。在整个项目中,还有其他的很多测试需要这些人来完成,如:功能测试、验收测试、性能测试、环境测试、有效性测试、正确性测试、正规分析等等。

  8没有真实的环境运行单元测试。

有时候因为模块开发计划的问题,有的模块没办法走通正常的流程,但是我们现在所讨论的只是针对开发者的单元测试。也就是说,你可以自己在数据库创建测试数据,或者使用mock对象,来完成测试。

  

题外话

 写这篇文章,没别的意思,就想来说明,单元测试的重要性,呼吁公司上下重视起测试工作,为提交一个高质量的应用系统给客户而努力.


TAG:

引用 删除 xiaoler   /   2010-08-23 16:27:42
单元测试在国内重视程度确实不够,多谢楼主的呼吁,不过单元测试确实需要花费时间和人力成本,建议看看C++test专业测试博客上面关于单元测试的一些论述:www.mytestlife.com
peterz的个人空间 引用 删除 peterz   /   2009-03-25 22:04:43
5
 

评分:0

我来说两句

Open Toolbar