软件测试系列--单元测试(Unit Testing)
一、单元测试的概念
单元测试(Unit Testing)是对软件基本组成单元进行的测试,如函数(function或procedure)或一个类的方法(method)。当然这里的基本单元不仅仅指的是一个函数或者方法,有可能对应多个程序文件中的一组函数。
单元也具有一些基本的属性。比如:明确的功能、规格定义,明确的与其他部分的接口定义等,可清晰地与同一程序的其他单元化分开来。
二、单元测试的目的
单元测试的目的在于发现各模块内部可能存在的各种错误,主要是基于白盒测试。(也就是说,在单元测试过程中,用的最多的是白盒测试方法,也可能会有灰盒或者黑盒。单元测试和白盒测试是不同的划分,不存在包含关系)。
在单元测试阶段对应的文档是详细设计文档(LLD);对应的代码就是单元代码,因此单元测试的目的主要有3点:
1、验证代码是与设计相符合的;
2、发现设计和需求中存在的错误;
3、发现在编码过程中引入的错误。
三、单元的常见错误
单元的常见错误一般出现在以下五个方面,因此这五个方面是单元测试应该关注的重点。
1、单元接口。
2、局部数据结构。
3、独立路径。
4、出错处理。
5、边界条件。
四、如何进行单元测试
在单元测试时,由于单元本身不是一个独立的程序,一个完整的可运行的软件系统并没有构成,所以需要设置一些辅助测试单元,辅助测试单元有两种,一种是驱动单元,另外一种是桩单元。
1、驱动单元(Driver):用来模拟被测单元的上层单元,相当于被测函数的主函数,如main函数。所以驱动单元主要完成以下4个步骤:
(1)接受测试数据,包含测试用例输入和预期输出;
(2)把测试用例输入传送给被测单元,驱动被测单元测试;
(3)将被测单元的实际输出和预期输出进行比较,得到测试结果;
(4)将测试结果输出到指定位置。
2、桩单元(Stub):用来代替被测单元工作过程中调用的子单元。
桩单元模拟的单元可能是自定义函数:这些自定义函数可能尚未编写完成,为了测试被测单元,需要构造桩单元来代替它们,可能存在错误,会影响测试结果,所以需要构造正确无误的桩单元来达到隔离的目的。
驱动单元和桩单元都是额外的开销,虽然在单元测试的时候必须写,但是并不需要作为最终的产品提供给客户。
五、单元测试策略
一般的单元执行策略有三种:孤立的单元测试策略(Isolation Unit Testing),自顶向下的单元测试策略(Top Down Unit Testing)和自底向上的单元测试策略(Bottom Up Unit Testing)。需要注意的是:在集成测试中也有自顶向下和自底向上的测试策略,但是测试对象不同。
1、孤立的单元测试策略(Isolation Unit Testing)
方法:不考虑每个模块与其它模块之间的关系,为每个模块设计桩模块和驱动模块,每个模块进行独立的单元测试。
优点:这个方法比较简单,最容易操作,可以达到很高的结构覆盖率,可以并行开展,该方法是纯粹的单元测试。
缺点:桩函数和驱动函数工作量很大,效率低。
2、自顶向下的单元测试策略(Top Down Unit Testing)
方法:先对最顶层的单元进行测试,把顶层所调用的单元做成桩模块,其次对第二层进行测试,使用上面已经测试过的单元做驱动模块,以此类推,直到测试完所有模块。
优点:可以节省驱动函数的开发工作,效率高。
缺点:随着被测单元一个一个被加入,测试过程将变得越来越复杂,并且开发和维护的成本将增加。
3、自底向上的单元测试策略(Bottom Up Unit Testing)
方法:先对最底层的模块进行单元测试,将模拟调用该模块的模块设置为驱动模块,然后再对上面一层做单元测试,用下面已经测试好的模块做桩模块,以此类推,直到测试完所有模块。
优点:可以节省桩函数的开发工作量,测试效率较高。
缺点:不是纯粹的单元测试,底层函数的测试质量对上层函数的测试将产生很大影响。