单元测试是对软件基本组成单元/模块进行的测试,又称为模块测试。基本单元/模块可以是函数、类实例、方法、存储过程,也可以是任何具有明确功能、规格定义、明确接口定义、并且其规模是一般比较小的程序代码模块的组合体。

  1、概述

  单元测试是对软件基本组成单元/模块进行的测试,又称为模块测试。基本单元/模块可以是函数、类实例、方法、存储过程,也可以是任何具有明确功能、规格定义、明确接口定义、并且其规模是一般比较小的程序代码模块的组合体。

  单元测试的重点在于发现程序设计或实现的逻辑错误,使问题及早暴露,便于问题的定位解决。

  单元测试中多采用白盒测试和黑盒测试相结合的方法,既关注单元功能,也关注程序模块的逻辑结构。两者结合起来,既可以避免由于过多关注路径而导致测试工作量很大的问题,又可以避免因从外部设计测试用例而可能丢失一些路径的问题。

  现今,更多观点认为单元测试应该由编码人员实施,笔者认为这种观点是有道理的。毕竟由测试人员实施单元测试比编码人员实施的工作量更大。当然,如果对于测试航空、航天、医疗等关系重大生命、财产的软件系统来说,需要投入大量的资源来保证系统质量时,则可以采用测试人员实施单元测试的策略。

  单元测试的重点应该以功能测试为主,同时统计测试的覆盖率,并且测试模块的输入/输出接口是否正确,内部的数据流是否正确等。

  功能测试主要测试模块是否正确实现了设计要求的功能,以及有无遗漏的功能。这里有一个功能覆盖的概念。因为被测试模块可能包括多个功能点,在做测试时,设计测试用例要覆盖这些功能点,以保证这些功能点经过测试。一般要求功能覆盖100%。

  覆盖率一般要求进行语句覆盖率和分支覆盖率,同时要求测试所有的关键路径。关键路径的表达不是很明确,但是如果要求做基本路径集覆盖测试,即使是一个比较小的模块也是很难做到的。如果使用单元测试工具(如CppUnit、Junit等),则可以统计覆盖率。

  单元测试结束后,如果有些分支由于各种条件无法覆盖,则需要给出原因说明。

  2、单元测试的步骤

  单元测试过程包括计划、设计、执行、评审等几个步骤,分别如下所述。

  ① 计划:确定测试需求,制订测试策略,确定测试所用资源(如人员、设备等),创建测试任务的时间表。这部分工作可以简单描述。

  ② 设计:设计单元测试模型,制订测试方案,制订具体的测试用例,创建可重用的测试脚本。

  ③ 执行:执行测试用例,对单元模块进行测试,验证测试的结果并记录测试过程中出现的缺陷。

  ④ 评审:对单元测试的结果进行评审。主要进行测试完备性评估。

  由于单元模块往往不是一个独立的程序,在设计时,要考虑单元模块同其他模块的联系,用桩模块和驱动模块模拟所测模块相联系的其他模块。由被测试模块、驱动模块和桩模块共同构成可运行的程序。

  驱动模块和桩模块的定义如下所述。

  驱动模块:相当于被测试模块的主程序,用于接收数据或产生数据,把数据传递给被测试模块,再输出实测结果,或把实测结果同预期结果进行比对。

  桩模块:也称为存根模块。用以代替被测试模块调用的子模块。桩模块可以用做数据处理,不需要把模块的所有功能都模拟,可以简单地返回一个值。

  3、单元测试的内容

  1)单元功能测试

  单元功能测试的内容如下:

  单元设计的功能点是否全部实现。
  运算的优先级和先后执行顺序是否正确。
  计算中精度的处理是否正确。
  计算中的误差是否会无限放大。

  2)模块接口测试

  在单元测试的开始,应对所测模块的数据流进行测试。如果数据不能正确地输入和输出,不能进行其他测试。

  对模块接口可能需要进行下面的测试外包项目:

  调用所测模块时的输入参数与模块的形式参数在个数、属性、顺序上是否匹配。
  所测模块调用子模块时,它输入给子模块的参数与子模块的形式参数在个数、属性、顺序上是否匹配。
  是否修改了只做输入用的形式参数。
  输出给标准函数的参数在个数、属性、顺序上是否正确。
  全局变量的定义在各模块中是否一致。
  限制是否通过形式参数来传送。
  模块对外部文件、数据库进行输入/输出时,必须对文件操作进行测试。例如,缓冲区的大小、是否在读写文件前打开文件,在结束前关闭文件等。