一、单元测试的意义
单元测试会为我们的质量做保证。编写单元测试就是用来验证这段代码的行为是否与我们期望的一致。有了单元测试,我们可以自信的交付自己的代码,而没有任何的后顾之忧。
我们在编码时,一定会反复调试保证它能够编译通过。如果是编译没有通过的代码,没有任何人会愿意交付给Boss。但代码通过编译,只是说明了它的语法正确;我们却无法保证它的语义也一定正确,没有任何人可以轻易承诺这段代码的行为一定是正确的。
从成本角度考虑,BUG发现越早越好,加强单元测试力度有利于降低缺陷定位和修复难度,从而降低缺陷解决成本,同时加强单元测试也减轻了后续集成测试和系统测试的 负担。据业界统计,如果一个BUG在单元测试阶段发现花费是1的话,到集成测试就变为10,到系统测试就高达100,到实际推向市场量产后就高达 1000,所以,进行充分的单元测试,是提高软件质量,降低开发成本的必由之路。但单元测试在目前国内软件企业中开展得并不好,一方面是由于对单元测试重 视程度不够,测试投入不足,另一方面是由于在单元测试实践方面积累得也不够,单元测试处于一种摸索状态。
单元测试不仅仅是作为无错编码一种辅助手段,在一次性的开发过程中使用,单元测试必须是可重复的,无论是在软件修改,或是移植到新的运行环境的过程中。因此,所有的测试都必须在整个软件系统的生命周期中进行维护。
单元测试与其他测试不同,单元测试可看作是编码工作的一部分,应该由程序员完成,也就是说,经过了单元测试的代码才是已完成的代码,提交产品代码时也要同时提交单元测试代码。测试部门可以对单元测试的过程以及结果作一定程度的审核,作为集成和系统测试准入的一种标准。
二、如何做好单元测试
1)组织结构应该保证测试部门参与单元测试
目前普遍都认为单元测试应该由开发人员开展,这是因为从单元测试的过程看,单元测试普遍采用白盒测试的方法,离不开深入被测对象的代码,同时还需要构造驱动模块、桩函数,因此开展单元测试需要较好的开发知识。从人员的知识结构、对代码的熟悉程度考虑,开发人员具有一定的优势。
单元测试由开发人员进行能带来一些特别的收益。我们知道,在实践中开发人员进行单元测试一般推荐采用交叉测试的方法,例如由被测单元的调用方进行该单元 的测试,即尽量避免对自己的代码进行单元测试。这种交叉的测试安排可以避免测试受开发思路影响太大,局限于原来的思路不容易发现开发过程中制造的问题;二 来也达到一个技术备份或充分交流的目的,这对组织非常有利。即使不采用交叉测试的方法,而安排单元的生产者自行开展单元测试,也是有很大的优越性的,其最 大的优点是快速。在人员紧张的情况下这种自行测试的安排也是不错的选择。
从经验值来看,单元测试投入和编码投入相比基本上是一比一,如果由专职测试队伍来进行单元测试,维持这样庞大的单一任务队伍显然是不合适的,对于一般企业来说也是不小的成本负担。
以上谈的是由开发人员进行单元测试的优点,其中主要是从单元测试的效率角度来考虑。但是从单元测试效果的角度考虑,必须从组织结构上保证测试部门参与单元测试,这是因为:
首先,从目前国内企业普遍现状来看,测试人员质量意识要高于开发人员,测试人员参与单元测试能够提高测试质量。
其次,对被测系统越了解,测试才有可能越深入,测试人员参与单元测试,将使得测试人员能够从代码级熟悉被测系统,这对测试人员后期集成测试和系统测试活动非常有帮助,会很大的提升集成测试和系统测试质量。
测试部门以何种方式参与单元测试,应该结合软件组织的实际情况来定。如果软件组织测试充分,测试人员对开发人员的比例较高,那么可以由测试人员独立承担 部分重要模块的单元测试工作;如果测试资源不足,测试人员对开发人员的比例较低,那么可以采取由测试人员进行单元测试计划、单元测试设计的工作,而单元测 试的实现和执行由开发人员来完成;而如果测试资源非常缺乏或测试人员素质不够全面,连单元测试计划、单元测试设计都无法承担,那么测试部门至少应该参与开 发过程的各相关单元测试文档、单元测试报告的评审,保证单元测试的质量。
2)制订单元测试的过程定义
软件质量的提高需要规范的流程,对软件开发过程进行管理也需要依据规范的过程定义。要提高单元测试的质量,首先要制定规范的单元测试过程,各生产部门可以依据单元测试过程定义开展各自的工作,共同保证单元测试的质量。
单元测试过程的定义需要参照企业的实际情况,例如阶段划分可以分为四个阶段:计划、设计、实现、执行。
其中计划阶段应当考虑整个单元测试过程的时间表,工作量,任务的划分情况,人员和资源的安排情况,需要的和测试方法,单元测试结束的标准等,同时还应当考虑可能存在的,以及针对这些风险的具体处理办法,并输出《单元测试计划》文档,作为项目中整个单元测试过程的指导。
设计阶段需要具体考虑对哪些单元进行测试,被测单元之间的关系以及同其它模块单元之间的关系,具体测试的策略采用哪一种、如何进行单元测试用例的设计、如何进行单元测试代码设计、采用何种工具等,并输出《单元测试方案》文档,用来指导具体的单元测试操作。
实现阶段需要完成单元测试用例设计、脚本的编写,测试驱动模块的编写,测试桩模块的编写工作,输出《单元测试用例》文档、相关测试代码。
执行阶段的主要工作是搭建单元测试环境,执行测试脚本,记录测试结果,如果发现错误,开发人员需要负责错误的修改,同时进行回归测试,该阶段结束需要提交《单元测试报告》。我们可以将设计和实现阶段合并,输出《单元测试用例》文档、相关测试代码。
3)必须制订覆盖率指标和质量目标来指导和验收单元测试
单元测试必须制订一定的覆盖率指标和质量目标,来指导单元测试设计和执行,同时作为单元测试验收的标准。设计用例时,可针对要达到的覆盖率指标 来设计用例,而在测试执行时,可以依据覆盖率分析工具分析测试是否达到了覆盖率指标,如果没达到,需要分析哪些部分没有覆盖到,从而补充用例来达到覆盖率 指标。而单元测试质量目标的制订,需要符合软件企业的实际过程能力,这依赖于软件企业对以前单元测试过程度量数据的积累,不能凭空制造出来。有了以前度量 数据的积累,完全可以了解当前组织的单元测试能力,例如单元测试每千行代码发现的缺陷数是多少。如果单元测试统计结果没有落到这个质量目标范围内,说明单 元测试过程中某些方面存在一些问题,需要对测试过程进行分析后找出问题原因进行改进。
这些指标确定下来后,一定要严格推行。定会有一些人找出各种理由证明覆盖率指标达不到等等,这需要质量部门根据实际情况分析指标是否合理。实际 证明有一个相对简单的标准也比没有标准要好得多,但显然,通过推行硬性指标,单元测试发现的问题数目比没有标准前至少增加了2倍。
4)单元测试者技能的提高
1、加强对单元测试人员的技能
单元测试的质量很大程度上决定于进行单元测试的人的技术水平。如果测试者不具备单元测试的知识,那么应该对测试者进行相关的培训。一个没有做过 单元测试人,不经过培训初次是很难做好单元测试的。单元测试在详细设计阶段结束时开始,但是单元测试相关培训应该尽早准备和计划,培训可以分两个阶段,每 个阶段的内容类似。第一阶段是写单元测试方案前,培训对象为测试方案的写作者和详细设计的写作者,这样可以在设计时多考虑可测试性,培训的内容为单元测试 基本概念、单元测试分析方法、单元测试用例的写作、单元测试标准的明确;第二阶段为单元测试执行前,对象为测试执行者,培训内容为具体单元测试的执行,包 括驱动函数、桩函数的构造、覆盖率测试工具的使用(TrueCoverage、Logiscope等)、利用自动化单元测试框架构造单元测试自动化 (TCL、CppUnit、JUnit等)。培训过程中最好结合实例穿插其中,会比较生动,而且增强理解。
通过以上的系统培训,可以统一单元测试方法、明确单元测试的标准、掌握单元测试基本技能,为后期单元测试的顺利开展扫平道路。
2、必须引入工具进行辅助
单元测试非常需要工具的帮助,特别是覆盖率工具不能缺少,否则用例执行后无法得到测试质量如语句覆盖、路径覆盖等情况,也就无法对被测对象进行 进一步的分析。应用较广的分析覆盖率的工具有Logiscope、TrueCoverage、PureCoverage等,它们的功能有强有弱,可以根据 实际情况采用。
为了提高单元测试的效率,特别是提高进行回归测试时的效率,需要在单元测试中引入自动化。目前常用的方法是采用TCL语言编写扩展指令,构造自己的单元测试自动化。也可以直接采用开源的自动化测试框架如CppUnit、JUnit等。
此外,在单元测试之前,还需要利用PC_Lint对被测代码进行检查,排除代码语法错误,确保进行单元测试的代码已经具备了基本质量,保证单元测试能够顺利进行,提高单元测试执行效率。
3、单元测试者加强对被测软件的全面了解
单元测试的目的除了要发现编码中引入的错误和发现代码与详细设计不一致的地方之外,还有一个目的是为了保证详细设计的质量。因为测试分析和测试用例设计需要依据详细设计来进行,这个过程实际上是对详细设计的重新检视,在这个过程中会发现以前评审中没有发现的问题。
三、我们公司的单元测试 我们公司的单元测试才刚刚起步,质量体系中尚无明确的规范,程序员对单元测试的意识也较淡薄。虽然在推行单元测试上取得了一些进步,但很难落实 到实际的环节上,很多都是走过场的。不少程序员觉得任务大,时间赶,人手少,一接到任务就是先赶代码完成工作量了,这其实是很普遍的现象。而且,绝大部分 程序员从骨子里不喜欢写单元测试,这却是不争的事实。我们公司的开发人员在单元测试上多是走过场,而测试人员也只涉及到存储过程的单元测试,且没有单元测 试用例,测试方法存在误区,导致测试带有随意性,效率低下。
要做好单元测试,还必须充分考虑到公司自身的实际情况。基于我们公司目前的诸多现状,结合项目具体实际情况,在公司某一项目中,对单元测试做了如下理论结合实际的应用。
1、项目经理在项目计划的过程定义文件中明确单元测试作为本项目的过程,确定在单元测试的各个阶段的工作产物;
2、项目经理制定单元测试计划,明确测试目标、测试方法、准入准则、准处准则、单元测试数据、单元测试工具、人力资源计划、进度计划;
3、开发人员在编码前设计测试用例,并且准备单元测试代码及设计文档,项目组组织人员评审,测试人员必须参加;
4、开发人员在编码完成提交产物前,必须做单元测试,可以是自测,也可以是开发人员互测,发现的缺陷必须提交缺陷库,并提交单元测试报告。在人力资源紧张时,可以由测试人员执行单元测试;
5、有了单元测试的缺陷数据,我们就可以分析,一般常见的缺陷有哪些类型,如何改进;还可以发现哪些开发人员的编码质量,为奖惩提供依据。
四、结论和展望
总而言之,单元测试将让我们的开发工作变得更加轻松,让我们对自己的代码更加自信。无论是项目的规模大小,无论是时间紧迫的项目还是时间宽裕的项目,只要代码不是一次写完永不改动,编写单元测试就一定超值。我希望它能成为我们公司编码过程中不可缺少的一部分。
单元测试仅仅是软件质量保证的一个环节,软件的质量由组织、流程和技术三个维度来决定,任何一个维度都不能单独决定软件的质量。好的组织结构可 以保证流程的顺利实施,好的流程能提高软件开发的规范性和可控性,从而提高软件开发的效率和质量,而采用了好的技术和有好的技术的载体--人,则从根本上 保证了软件的质量。
该项目在落实以上措施后,达到了一下效果:
1、在一定承担上提升了软件交付质量;
2、测试部门反映:有效降低集成和系统测试投入的成本;
3、项目执行周期比预期的缩短。
因此,论证了单元测试在软件生产过程中作用。