单元测试指南
单元测试指南
1、单元测试简介
测试类型划分
-单元测试(UT) 验证详细设计
-集成测试(IT) 验证概要设计
-系统测试(ST) 验证需求分析
-验收测试(AT) 验证 SOW
缺陷分布比例
消除缺陷的成本比较
概念
单元测试是对软件基本组成单元进行的测试,这里的基本单元不一定是指一个具体的函数或一个类的方法(method),“单元”具有一些基本属性,如:明确的功能、规格定义,明确的与其他部分的接口定义等,可清晰地与同一程序的其他单元划分开来。在具体实现时,也可能对应的是多个程序文件中的一组函数。
单元测试与集成测试的区别
单元测试与集成测试相比,测试对象有所区别,集成测试的被测对象是在概要设计中规划的模块及这些模块间的组合,这里,不同模块往往是分配给不同的某个(或某组 )程序人员开发。单元测试的测试对象是这些模块下的实现具体功能的单元,一般是对应详细设计中所描述的设计单位
单元测试与系统测试的区别
单元测试与系统测试相比,其侧重点在于发现程序设计或实现的逻辑错误,基本属于白盒测试的范畴;单元测试使问题及早暴露,也便于问题的定位解决,单元测试属于早期测试,因而错误发现后就能明确知道是由某一单元产生的;单元测试允许多个被测单元的测试工作同时开展。
白盒测试(White Box Testing)基本概念
-根据应用软件代码的内部逻辑,按照代码的语句、分支、路径和条件进行测试。
-也称结构测试或逻辑驱动测试
-开发人员执行
-测试程序内部,基于内部逻辑结构的测试。
白盒测试应遵循的原则
对程序模块中所有独立执行路径至少测试一次;
对所有的逻辑判定,取“真”与取“假”的两种情况 都至少要测试一次;
在循环的边界和运行界限内执行循环体;
测试内部数据的真实有效性。
2、单元测试过程划分
单元测试的过程划分
单元测试的步骤
3、单元测试模型设计
单元测试模型的设计
-
因为单元本身不是一个独立的程序,一个完整的可运行的软件系统并没有构成,所以在测试模型设计中必须为每个单元测试开发驱动模块(Driver)和 桩模块(Stub)。在绝大多数应用中,驱动模块只是一个接收测试数据,并把数据传送给(要测试的)模块,然后打印相关结果的“主程序”。“桩模块”的功能是替代那些隶属于本模块(被调用)的模块,桩模块要使用子模块的接口,作一些少量的数据操作,并验证打印入口处的信息,然后返回。
-
构造 单元的测试模型 的主要工作有:
构造 最小运行调度系统,即驱动模块,用以模拟 被测模块的上一级模块;
模拟 实现单元接口,即单元函数需调用的其他函数接口,即桩模块;
模拟生成测试数据或状态,为单元运行准备动态环境
4、单元测试范围
单元测试内容
单元测试主要测试以下五个方面的内容
-单元(模块)接口(interface)
-局部数据结构(local data structures)
-边界条件(boundary conditions)
-独立路径(independent paths)
-出错处理(error handling paths)
单元测试中接口(Interface)测试内容
-输入参数个数与形参个数是否相等?
-输入参数与形参属性是否匹配?
-输入参数与形参单位是否匹配?
-输入参数传递顺序是否正确?
-输入参数是否可以改变?
-全局变量定义跨模块时是否保持一致?
涉及I/O的检查列表
1、文件属性是否正确?
2、OPEN/COSE 语句是否正确?
3、格式归约是否和I/O语句匹配?
4、缓冲区大小是否和记录大小匹配?
5、文件是否在打开前被使用?
6、是否处理了文件结束条件?
7、是否处理了I/O操作?
8、在输出信息中是否有文本错误?
单元测试中本地数据结构(Local Data Structures)测试内容:
-不正确或者不一致的类型描述。
-错误的初始化或缺省值。
-不正确的变量名字。
-不一致的数据类型。
-下溢、上溢和地址错误。
-未初始化的内存读写。
-内存泄漏
单元测试中边界值分析(Boundary Value Analysis)测试内容
-对于单个输入值 n,需要测试三种情况:
Test(n-1),Test(n),Test(n+1)。
-对于有范围的取值(a,b),利用边界值分析方法需要测试六种情况
Test(a-1),Test(a),Test(a+1),Test(b-1),Test(b),Test(b+1)
独立路径(Independent Path)测试:
确保每一段程序代码都能被测试到。举例如下:
-
编号 2. 画出流图(Flow Graph) 3. 确定独立路径
单元测试中错误处理(Error Handling)测试内容:
-对错误的描述含糊不清。
-所报的错误与实际的错误不一致。
-错误在应用程序处理之前已被系统处理。
-违例条件处理不正确。
-错误描述不足以定位错误。
...
5、单元测试用例设计
单元测试用例设计的原则
单元测试用例的设计根据是软件的设计说明书,即详细设计文档。对于单元测试,测试用例用来证明一个独立的单元是否实现了单元设计说明书中的要求。一个完整的单元测试不仅仅要进行正向测试,即测试被测单元是否作了它应该作的事情(满足设计说明书要求),同时还应该作逆向测试,即被测单元有没有做并不希望它做的事情(即设计说明书以外的事情)。
单元测试用例设计中的覆盖率要求
在单元测试方案中,要明确说明量化的被测试单元需要达到的覆盖率指标。
覆盖有两种含义: 一是 逻辑覆盖(代码覆盖),我们常说 的语句覆盖、判断覆盖和条件覆盖等都属于代码覆盖的范畴,这是一种常用的 白盒测试方法;
二是 功能覆盖,属 黑盒的范畴,用来指出 测试用例 是否已经覆盖了 程序应该提供的功能。逻辑覆盖率 是考核 单元测试质量 的一个关键指标。
单元测试方案中的 覆盖率指标 即指 逻辑覆盖率指标。
逻辑覆盖分类
语句覆盖:
- 设计若干测试用例,运行被测程序,使得 每一个可 执行语句至少执行一次;
判断覆盖:
- 设计若干测试用例,运行被测程序,使得程序中每个判断的取真分支和取假分支至少执行一次。这里,取假分支可能没有写出来,如 if 语句缩略 else这种情况;
条件覆盖:
- 设计若干测试用例,运行被测程序,使得程序中每个判断的每个条件的可能取值至少执行一次。
在单元测试方案中,要明确对所测单元的覆盖率要求并注明得到被测单元测试覆盖率的方法。 根据被测试对象的不同,可能有不同的覆盖率指标要求。一般要求每个被测单元至少达到 100% 的语句覆盖。
6、单元测试用例设计步骤
单元测试用例设计步骤
-为系统运行起来而设计用例
-为正向测试而设计用例
-为逆向测试而设计用例
-为满足特殊需求而设计用例
-为 代码覆盖 或 覆盖率指标 完成而设计用例
为系统运行起来而设计用例
单元测试方案中的第一个测试用例最有可能是用最简单的方法执行被测单元。当这第一个测试用例可以正常运行,至少知道测试环境和被测试单元是可用的,如果没有能够执行,那么最好重新调试(Debug),也就是说还不具备开始 单元测试的条件。
为正向测试而设计测试用例
测试用例的设计者应该通读相关的设计说明,每一个测试用例,就是有针对地测试详细设计说明书中的一项或多项内容来设计的。当涉及到不止一个设计说明书时,最好在测试方案中的测试用例与主要的设计说明书中的描述顺序相对应。正向测试的用例就是验证设计说明书所对应的功能项或性能指标能否兑现。边界值的测试用例也可以在此时加入。
为逆向测试而设计用例
逆向测试的用例就是用来验证被测的软件单元有没有做它不应该做的事情。此步骤主要依靠错误猜测的方法进行测试用例的构造。
为满足特殊需求而设计用例
从系统的性能、安全性、保密性的角度来设计测试用例也是十分必要的。尤其对于安全及保密要求较高的系统,在测试方案中,特别的标明用来进行安全及保密的测试用例是有好处的。
为代码覆盖而设计用例
设计好的测试用例是可以保证较高的代码测试覆盖率的。在单元测试方案中,为了达到特定的测试覆盖目标,可能还需要补充一些测试用例。
当测试覆盖率测试用例设计好后,测试方案基本完成,就可以具体执行测试用例了。
7、单元测试用例设计方法
单元测试用例设计方法
- 规范(规格)导出法
-等价类划分法
-边界值分析法
-状态转移测试法
-分支测试法
-条件测试法
-数据定义-使用测试法
-内部边界值测试法
-错误猜测法
规范(规格)导出法
-
规范导出的测试是根据相关的规范描述来设计测试用例。每一个测试用例用来测试一个或多个规范陈述语句。一个比较实际的方法是根据陈述规范所用语句的顺序来相应地为被测单元设计测试用例。
例如,考虑一个计算平方根的函数的规范:
输入:实数
输出:实数
规范:当输入一个 0 或 比 0 大的数时,返回其正的平方根;当输入一个小于 0 的数时,显示错误信息“平方根非法-输入值小于0”,并返回 0;库函数 Print_Line 可以用来 输出错误信息。
在这个规范中有三个陈述,可以用两个测试用例来对应:Print_Line 用来传送错误信息。
测试用例1:输入4,输出2
对应规范中的第一句陈述(“当输入一个0或比0大的数时,返回其正的平方根”) -
测试用例 2:
- 对应规范中的第二、第三句陈述:(“当输入一个小于0的数时,显示错误信息“平方根非法-输入值小于0”,并返回0;库函数 Print_Line可以用来输出错误信息”)
- 规范倒出测试用例 和 规范陈述 之间做到了很好的对应,加强了规范的可读性和可维护性。但它是一种 正向的测试用例设计 技术,所以需要 逆向的测试技术 来对测试用例进行补充以达到更充分的测试。
- 规范倒出测试的变化形式可以应用到 保密分析、安全分析、软件故障分析,或其它对单元规范做出补充的文件上去。
等价类划分法
-
等价类划分是一种更正式的测试用例设计方法,它基于对被测单元的输入、输出所做的划分,对每一个划分中的所有输入,被测单元有等价的行为。划分也可以根据软件所能存取的数据确定,包括时间、输入输出顺序、状态。
-
等价类划分假定某一特定的等价类中的所有值对于测试目的来说是等价的。所以可以在每个等价类中找一个值做为测试用例。考虑前边的平方根函数的例子。平方根函数的输入可以有两个划分,输出可以有两个划分:
输入划分 输出划分
(i) <0 (a) >=0
(ii) >=0 (b) Error
这四个划分可以用两个测试用例测试:
测试用例1:输入4, 输出 2 对应于(ii)和(a)
测试用例2:输入-10,输出0,输出错误信息“平方根错误-非法输入负值” 对应与(i)和(b)
对于象平方根这样的函数,其等价类的划分是很简单的。当软件变得复杂时,等价类的区分 以及 相互之间的作用关系 也相应复杂,不能方便地应用这种方法。等价类划分方法基本上属于正向测试技术。
边界值分析法
边界值分析使用与等价类测试方法相同的等价类划分,只是边界值分析假定错误更多地存在于两个划分的边界上。 相应地为 边界上 及其 两侧的情况 设计测试用例。
-
上面的例子,
1)0及比0大的划分包括了从0到最大正实数的范围;
2)小于0的划分包括了从 0 到最小负实数的范围。输出有一个边界 0。
测试用例1:输入{最小负实数},返回0,输出“平方根错误-非法负值输入” 对应于划分(i)的下边界
-
测试用例2:输入{恰比0小},返回0,输出“平方根错误-非法负值输入”对应于划分(i)的上边界
-
测试用例3:输入 0,输出 0 对应于恰在划分(i)上界之外,划分(ii)的下界,划分(a)的下界
-
测试用例4:输入{恰比0大},返回{输入的正的平方根} 对应于划分(ii)的下界之内
-
测试用例5:输入{最大正实数},返回{输入的正的平方根} 对应于划分(ii)的上界,划分(a)的上界跟等价类划分测试一样,边界值测试在软件变得复杂的时候也会变得不实用。边界值分析对于非向量类型的值(如枚举类型的值)也没有意义。在上面的例子中划分(b)实际上没有边界。
状态转移测试法
对于那些以状态机作为模型或设计为 状态机的软件,状态转移测试是合适的测试方法。测试用例通过 能导致状态迁移的事件 来测试状态之间的转换。用这种方法可以设计 逆向的测试用例, 如 状态 和 事件 的非法组合。
8、单元测试中的方法分类
黑盒测试
-
等价分类法、边界值分析、单元功能测试、错误推测法又称 功能测试 或 规格测试,黑盒测试的目的是验证单元指定的具体行为,而不必关注单元是如何实现这些行为的。 黑盒测试 依赖于单元的输入和输出。该方法测试用例的设计通常有三种方法:
-
等价类测试和边界值分析:
等价类是一种减少测试数据数量的一种手段。对于每一个操作,应确定 参数 和 对象状态 的等价类。等价类是一组值的集合,对于这组值,测试对象的行为表现相似。例如,一个集合有三个等价类:【 空集、包含一些元素的集合 和 满集】。设计测试用例时需知道代码如何使用。 -
单元功能测试:
黑盒测试的另一种形式是以模块单元的功能为基础来建立测试数据,及对模块单元规格的验证。 -
错误推测法:
1)依靠经验和知觉推测程序中可能存在的各种错误, 从而有针对性地设计测试用例,验证推测;
2)作为一种辅助手段,即:首先用其他方法设计测试用例,再用错误猜测法补充一些实例。
白盒测试:
逻辑覆盖、条件覆盖、基本路径测试
1、【逻辑覆盖】是以程序内部的逻辑结构为基础的设计测试用例的技术,属于白盒测试范畴的一种基本方法 ;分为六种方法:语句覆盖、判定覆盖、条件覆盖、判定—条件覆盖、条件组合覆盖、路径覆盖;
2、【条件覆盖】设计若干测试用例,运行被测程序,使程序中每个判定语句中的每个条件 均按“真”、“假”值至少执行一次。
3、【路径覆盖】设计足够的测试用例,覆盖程序中所有可能的路径。
- 单元性能分析测试
它监测代码的运行并分析有关方面的性能, 如性能瓶颈、低效等。 - 单元可靠性测试
它监测代码的运行并查出导致系统崩溃和性能下降的运行错误,如内存泄漏、使用未初始化的内存、内存堆栈错误等,可以使用测试工具在测试过程中来进行检测,常用的测试工具有 PURIFY、JPROBE 等。 - 单元测试多采用【白盒测试】技术,系统内【多个单元可并行地】进行测试
9、单元测试的评估
- 评估方法
对单元测试的评估一般采用 测试覆盖 来描述测试完成的程度。有两种方法 可确定 测试覆盖:
需求覆盖(主要用于黑盒测试)
代码覆盖(主要用于白盒测试、单元性能分析和运行错误测试)
这两种方法都可分析出 被测试的项目 占 总测试项目 的百分比,但它们
采用不同的收集信息和计算的方法。- 1、需求覆盖:使用用例、需求、用例流量或测试条件作为所有测试项目的量度,可用于测试设计期间。
- 2、代码覆盖:使用产生所有测试项目的代码,度量测试期间执行过的代码特性(如执行过的代码行数 或 经过的分支数目)。这种类型的覆盖量度仅能使用在代码生成后。
- 在此过程中,需确定所采用的方法,陈述度量如何收集、数据如何解释 和 量度如何使用。
单元测试评估实例-覆盖率结果分析
-
通讯机制 CSocktListener 类的单元测试代码覆盖率分析
+:调用到的 - :未调用到的 * : 程序中未出现的
-
覆盖率分析结果
通信机制有效代码(不包括测试用类和测试主程序的代码)中,共有142个函数;系统单元测试过程中遍历到的函数为 98个; 执行完测试用例程序后遍历到的函数为117个(除去虚函数,通信机制共包含125个有效函数),实际应用到的函数有110个。这样,函数覆盖率为 89%【98/110】,总的代码覆盖率为 73.3%【用工具测量得出】。
11、单元测试用例之范例
-
单元测试用例之范例-用例设计实例
-
单元测试用例之范例-语句覆盖