各种覆盖率方法介绍STIN-GZH提供作者:三原
下载:WWW.51CMM.COM
1 简介
1.1 代码覆盖率分析
这篇文章给出了一个完整的代码覆盖率分析方面的概念。
代码覆盖率分析是这样一个过程:
· 出程序经过一系列测试而没有执行的部分代码
· 创建一个附加的测试用例来增加覆盖率
· 决定代码覆盖的定量度量。
代码覆盖率分析的一个有效方面是:
· 识别出没有增加覆盖率的无效的测试用例。
覆盖率分析需要被测试程序的源代码,并且经常需要用一个特殊的命令重新编译它。这篇文章讨论你应当考虑你的测试计划中应该如何增加覆盖率分析的细节问题。覆盖率分析有一定的好处和弱点。你应该选择一个测量方法的范围。你应该建立一个覆盖率要达到的最小百分比,来决定你什么时候停止覆盖率分析。覆盖率分析只是许多测试技术的一种,你不能只是依靠它。
1.2 结构化测试和功能测试(Structural testing&Functional testing)
代码覆盖率分析是一种结构化测试技术(AKA glass box testing and white box testing). 结构化测试是比较被测试程序的行为和源代码的外观目的。和功能测试相比(AKA black-box testing), 功能测试是比较被测试程序的行为和确定的需求。结构化测试检查程序的工作,考虑结构中可能存在的逻辑缺陷。功能测试检查被测试程序的完成需求的能力,不考虑它是怎么工作的。
结构化测试也叫路径测试(path testing), 因为你选择测试用例来通过程序结构的路径。不要和路径覆盖率度量(path coverage)混淆,下面会介绍。
粗略的看,结构化测试似乎不安全,结构化测试不能发现需求疏忽的错误,但是,需求定义有时并不存在,而且并不完整。这个现象是实际存在的,当产品开发的时间线就要到的时候,当需求定义很少更新,产品自身代替了需求定义的作用的时候。
1.3 假定
一些基本原理的假定如下所列:
· Faults ―――和控制流相关的缺陷,你可以发现这些缺陷通过变更控制流[Beizer1990 p.60]。例如,一个程序写为"if (c)" 比"if (!c)"好。
· 你可以寻缺陷而不必知道这个缺陷可能引起的后果和所有测试的可靠性。
· 其它的假定包括可完成需求的定义、没有疏忽的缺陷和没有不可以达到的代码等。
2 基本的度量
有许多覆盖率度量存在,这里介绍一些基本的度量的益处和弱点。
2.1 语句覆盖(Statement Coverage )
这个度量报告每一个可执行语句是否被执行。也称为: 行覆盖( line coverage ) , 段覆盖(segment coverage ) [Ntafos1988], C1 [Beizer1990 p.75] 和基本块覆盖(basic block coverage)。基本块覆盖当每一个序列的语句是无分支的语句时和语句覆盖相同。这个覆盖度量的主要好处是它可以直接应用在目标码上,不需要对源代码进行处理。执行轮廓就完成了这个度量。这个覆盖度量的主要缺点是对一些控制结构很迟钝。例如,考虑下列的C/C++ 代码:int* p = NULL;
if (condition)
p = &variable;
*p = 123;
如果当condition 取假的情况下,语句覆盖率显示这四句都覆盖到了,但是代码执行是失败的。这是一个语句覆盖率的严重的缺陷,IF语句是很普通的一种情况。语句覆盖不能报告循环是否到达它们的终止条件―――只能显示循环是否被执行了。既然do-while 循环通常要至少执行一次,语句覆盖认为它们和无分支语句是一样的。
语句覆盖率对逻辑运算符反映是迟钝的(|| and &&)。
语句覆盖不能区分连续的switch 语句。
测试用例通常和判定有关而不是和语句有关。你可能不必用10 个单独的测试用例来测试一个有10 个无分支语句的语句,你可能只用一个测试用例就够了;考虑一个IF-else 语句,包含一条语句在then 子句,99 条语句在else 子句,当执行两个可能路径的其中之一时,语句覆盖率得到如下的结果: 1 或99 的覆盖率。基本块覆盖率就忽略了这个问题。
2.2 判定覆盖(Decision Coverage )
这个度量报告是否BOOL 型的表达式取值true 和false 在控制结构中被测试到了(例如if-statement 和while-statement)。整个的BOOL型的表达式被认为是取值一个true 和false,而不考虑是否内部包含了logical-and 或logical-or 操作符。另外,这个度量包括switch-statement cases, exception handlers, and interrupt handlers的覆盖.也被称为: 分支覆盖( branch coverage ) , 所有边界覆盖(all-edges coverage) [Roper1994 p.58], 基本路径覆盖(basis path coverage )[Roper1994 p.48], C2 覆盖[Beizer1990 p.75], 判定到判定路径覆盖(decision-decision-path 或DDP testing [Roper1994 p.39]. )"Basis path"测试就是选择路径来达到所有的判定覆盖.这个度量有语句覆盖的简单性,但是没有语句覆盖
的问题。
缺点是这个度量忽略了在BOOL 型表达式内部的BOOL 取值。例如考虑如下的C/C++/Java 代码:if (condition1 && (condition2 || function1()))
statement1;
软件测试的方法有哪些else
statement2;
这个度量可以完全可以不用调用function1. 测试表达是为真时可以取condition1 为true 和condition2 为true,测试表达是为假时可以取condition1 为false。
2.3 条件覆盖(Condition Coverage )
条件覆盖报告每一个子表达式的结果的true 或false 。logical-and 和logical-or 独立起来。条件覆盖独立的度量每一个子表达式.这个度量和decision coverage 相似,但是对控制流更敏感。但是,完全的条件覆盖并不能保证完全的判定覆盖。例如,考虑下列的C++/Java 代码。bool f(bool e) { return false; }
bool a[2] = { false, false };
if (f(a && b)) ...
if (a[int(a && b)]) ...
if ((a && b) ? false : false) ...
所有三个IF 语句不管a 和b 取值是什么,判定覆盖率只能达到50%。但是条件覆盖率却能达到100%。
2.4 多条件覆盖(Multiple Condition Coverage )
多条件覆盖报告每一个可能的BOOL 型子表达式的组合发生了。相对于条件覆盖,即通过logical-and 和logical-or 把子表达式独立起来相比, 多条件覆盖需要的测试用例是用一个条件的逻辑操作符的真值表来确定的。
对于C, C++和Java 等具有short circuit operators 的语言,多条件覆盖的益处是它需要一个彻底的测试。
缺点是它可能是非常冗长乏味的来决定一个需要的测试用例的最小设置,尤其是对于非常复杂的BOOL型表达式。另一个缺点是,这个度量需要的测试用例对于相似的复杂性的条件却需要非常大的变化。例如,考虑如下的C/C++/Java 条件:
要达到完全的多条件覆盖,第一个需要6个测试用例,
而第二个需要11 个测试用例。
但是两个条件却有相同的操作数和操作符。
对于Visual Basic 和Pascal 等不具有short circuit operators 的语言, 多条件覆盖对于逻辑表达式是非常有效的路径覆盖,具有相同的优缺点。考虑下列的
Visual Basic 代码:
If a And b Then
...
多条件覆盖需要四个测试用例,a 和b分别取值true 和false.
2.5 分支条件组合覆盖(Condition/Decision Coverage )
分支条件组合覆盖是条件覆盖(condition coverage)和分支覆盖(decision coverage)的一个混血。它有两者的简单性但是没有两者的缺点。
2.6 修正条件/判定覆盖(Modified Condition/Decision Coverage)
也被称为MC/DC 和MCDC.这个度量需要足够的测试用例来确定每个条件能够影响到包含的判定[Chilenski1994]的结果。这个度量是最早是被波音公司创建被用于航空软件中RCTA/DO-178B。这个度量起初是是设计来对于无short circuit operators 的语言。short circuit logical operators 在C, C++和Java 语言中的作用仅仅是当它们的结果能够影响到被包含的判定的评估条件。
当以下的需求遇到时,需要考虑用MCDC覆盖:
需求1: 每一个程序模块的入口和出口点都要考虑要至少被调用一次,每个程序的判定到所有可能的结果值要至少转换一次。
需求2:程序的判定被分解为通过逻辑操作符(AND, OR, etc.)连接为BOOL 条件。每一个条件对于判定的结果值是独立的,或者说单条件的变化将导致判决的变化。
所以,据以上的定义,以下三组数据是必须的。(单条件的变化将导致判决的变化)其中T1 & T2,或T1&T3已经满足要求1,但要求满足条件2,就必须存在同时存在T1&T2&T3。
T4:(F,F),是多余的,因为一个条件改变并不能导致判决的改变。
T1(T,T)与T2(T,F)表明Y独立影响了判决,Y的独立对;
T1(T,T)与T3(F,T)表明X独立影响了判决,X的独立对。
再如:
测试用例1 (T,T,T) 和测试用例5 (F,T,T) ,对于X独立。
测试用例2 (T,T,T) 和测试用例6 (F,T,T) ,对于X独立。
测试用例3 (T,T,T) 和测试用例7 (F,T,T) ,对于X独立。
测试用例2 (T,T,T) 和测试用例4 (F,T,T) ,对于Y独立。
测试用例3 (T,T,T) 和测试用例4 (F,T,T) ,对于Z独立。