1、软件测试概论之测试覆盖率,学习目标,掌握各种测试覆盖率的含义能计算各种测试覆盖率理解覆盖率在白盒测试中所起的作用,课程内容,覆盖率概念逻辑覆盖率其它覆盖率,覆盖率概念 覆盖率概念,覆盖率是用来度量测试完整性的一个手段。覆盖率是测试技术有效性的一个度量。 覆盖率=(至少被执行一次的item数)/ item的总数覆盖率大体可以分为两大类:逻辑覆盖和功能覆盖。测试用例设计不能一味追求覆盖率,因为测试成本随覆盖率的增加而增加,逻辑覆盖率 逻辑覆盖主要类型,语句覆盖判定覆盖条件覆盖判定条件覆盖路径覆盖,逻辑覆盖率 语句覆盖率,语句覆盖(Statement Coverage)的含义是,在测试运行被测程序后
2、,程序中被执行到的可执行语句的比率: 语句覆盖率=(至少被执行一次的语句数量)/(可执行的语句总数)根据对语句的理解,有两种计算结果:语句包含所有语句语句不包括分支语句,一种说法是所有语句;一种说法是去掉分支语句(如:if-else、switch-case、do-while、for);还有一种说法是有效语句(声明语句不算),逻辑覆盖率 语句覆盖率,在测试时,首先设计若干个测试用例,然后运行被测程序,是程序中的每个可执行语句至少执行一次A=2B=0CASE1X=3A=2B=1CASE2X=3CASE1能达到100%语句覆盖CASE2不能达到100%语句覆盖,只有75%或者50%,设计测试用例,使
3、代码的语句覆盖率达到100%Case1:a=2,b=0,x=3Case2:a=1,b=0,x=3,逻辑覆盖率 语句覆盖率,即使语句覆盖率达到100%也会有缺陷发现不了,所以覆盖率只是我们度量的手段。,逻辑覆盖率 分支覆盖率,分支覆盖(Branch Coverage)也叫判定覆盖(Decision Coverage),它的含义是,在测试时运行被测程序后,程序中所有判断语句的取真分支和取假分支被执行到的比率:判定覆盖率=(判定结果被评价的次数)/(判定结果的总数)需要搞清判定(或分支)和判定结果之间的关系;判定结果是判定的具体取值,为真或者为假。,逻辑覆盖率 分支覆盖率,在测试时,首先设计若干个测
4、试用例,然后运行被测程序,使得程序中每个判断的取真分支和取假分支至少经历一次,即判断的真假值均曾被满足。A=2B=0CASE1:路径aceX=3A=1B=0CASE2:路径abdX=1CASE1 CASE2能达到100%分支覆盖率,逻辑覆盖率 分支覆盖率,即使判定覆盖率达到100%也会有缺陷发现不了,所以覆盖率只是我们度量的手段。,逻辑覆盖率 条件覆盖率,条件覆盖(Condition Coverage)的含义是,在测试时运行被测程序后,所有判断语句中的每个条件的可能取值(真值和假值)出现过的比率:条件覆盖率=(条件操作数值至少被评价一次的数量)/ (条件操作数值的总数)需要搞清条件和条件操作数
5、之间的关系:条件操作数是条件的具体取值,取真或者取假。,逻辑覆盖率 条件覆盖率,在测试时,首先设计若干个测试用例,然后运行被测程序,要使每个判断中每个条件的可能取值至少满足一次。,逻辑覆盖率 条件覆盖率,CASE1、CASE2、CASE3能达到100%条件覆盖,逻辑覆盖率 条件覆盖率,1、CASE1 CASE2也能达到100%条件覆盖2、覆盖了条件的测试用例不一定覆盖了分支,分支覆盖率50%,逻辑覆盖率 分支条件覆盖率,分支条件覆盖(Branch Condition Coverage)也叫判定条件覆盖(Decision Condition Coverage),它的含义是,在测试时运行被测程序后
6、,所有判断语句中每个条件的所有可能值(为真为假)和每个判断本身的判定结果(为真为假)出现的比率:分支条件覆盖率=(条件操作数值或判定结果至少被评价一 次的数量)/(条件操作数值总数+判定结果总数)分支条件覆盖率实际上就是分支覆盖率和条件覆盖率的组合。,逻辑覆盖率 分支条件覆盖率,在测试时,首先设计若干个测试用例,然后运行被测程序,使得判断中每个条件的所有可能至少出现一次,并且每个判断本身的判定结果也至少出现一次,逻辑覆盖率 分支条件覆盖率,1、以上四个测试用例覆盖了100%条件、分支2、从路径角度看仅覆盖了3条路径,漏掉了路径acd,逻辑覆盖率 路径覆盖率,路径覆盖(Path Coverage
7、)的含义是,在测试运行时运行被测程序后,程序中所有可能的路径被执行过的比率:路径覆盖率=(至少被执行到一次的路径数)/(总的路径数),逻辑覆盖率 路径覆盖率,在测试时,首先设计若干个测试用例,然后运行被测程序,要求覆盖程序中所有可能的路径,路径覆盖率要达到100%:有几条路径就要设计几个用例,逻辑覆盖率 路径覆盖率,路径能否全面覆盖在软件测试中是个重要问题,如果程序中的每一条路径都得到考验,才能说程序受到了全面检验。即使对于路径数很有限的程序已经做到了路径覆盖,让然不能保证被测程序的正确性。A=2 or X1写错为A=2 and X=1每种覆盖率度量的时候都有其局限性,因此要把各种覆盖率组合起
8、来对测试进行度量。,A B XCASE1:2 0 3CASE2:1 0 1CASE3:2 1 1CASE4:3 0 1,逻辑覆盖率 覆盖率计算举例,执行测试用例(A=3,B=0,X=1),分别计算这种情况下的语句覆盖率(75%或者50%)、判断覆盖率(50%)、条件覆盖率(50%)、判断条件覆盖率(50%)、路径覆盖率(25%)执行测试用例(A=2,B=0,X=3)、(A=1,B=0,X=1),分别计算这种情况下的语句覆盖率(100%)、判断覆盖率(100%)、条件覆盖率(87.5%)、判断条件覆盖率(91.67%)、路径覆盖率(50%),其它覆盖率 功能覆盖率,功能覆盖率(Function
9、Coverage)是属于黑盒测试范畴功能覆盖率中最常见的是需求覆盖,其含义是通过设计一定的测试用例,要求每个需求点都被测试到需求覆盖=(被验证到的需求数量)/(总的需求数量)一个需求只有进行了充分的测试才能被认为覆盖到功能测试覆盖方面的自动化工具比较少,其它覆盖率 面向对象的覆盖率,结构化覆盖率用来度量测试的完整性已经被大家所接受。但是这个技术在面向对象领域却遇到了挑战。由于传统的结构化度量没有考虑面向对象的一些特性,如多态、继承和封装等。继承上下文覆盖(Inheritance Context Coverage),该覆盖率用于度量在系统中的多态调用被测试得多好。基于状态的上下文覆盖(State
10、-Based Context Coverage),该覆盖用于改进对带有状态依赖行为的类的测试。考虑面向对象的覆盖率都需要在结构化逻辑覆盖的基础上结合面向对象的一些特点。,其它覆盖率 继承对覆盖率度量的影响,测试用例A1测试了base:foo()和base:helper()之间的接口测试用例A2测试了base:bar()和derived:helper()之间的接口还需要测试base:foo()和derived:helper()之间的接口,以及base:bar()和base:helper()之间的接口需要补充测试用例:base.bar();derived.foo();,class Base pub
11、lic: void foo() . helper(); . void bar() . .helper(); .private: virtual void helper() . ;class Derived : public Base private: virtual void helper() . ;void test_driver() Base base; Derived derived; base.foo(); /Test Case A1 derived.bar(); /Tset Case A2,其它覆盖率 继承上下文覆盖,继承上下文覆盖提供了一个可替代的度量定义,它考虑在每个类的上下文内
12、获得的覆盖率级别。继承上下文定义把基类上下文内例行程序的执行作为独立于继承类上下文内例行程序的执行。同样,它们在考虑继承上下文内例行程序的执行也独立于基类上下文内例行程序的执行。为了获得100%继承上下文覆盖,代码必须在每个适当的上下文内被完全执行。,什么是上下文?就是环境,在多任务系统中,当一个任务的时间片段结束时,需要保存该任务当前的上下文,也就是运行的环境,以便下次该任务接着继续执行。,继承上下文判定覆盖=(累加每个上下文内执行到的判定结果数)/(上下文数上下文内的判定结果总数),其它覆盖率 基于状态的类的覆盖率特点,其它覆盖率 基于状态的类的覆盖率特点,状态迁移,状态转移图,状态事件表
13、,其它覆盖率 基于状态的类的覆盖率特点,有边界栈类的 类接口定义,符合接口覆盖 的用例,class BoundedStack public: BoundedStack(size_t maxsize); BoundedStack(); Void push(int); int pop(); struct underflow : std:exception ; struct overflow : std:exception ;,int test_driver() BoundedStack stack(2); stack.push(1); stack.pop(); /destructor called
14、 implicitly at end of block;,其它覆盖率 基于状态的类的覆盖率特点,int better_test_driver() BoundedStack stack(2); stack.push(3); /push() when empty stack.push(1); /push() when partially-full try stack.push(9); /push() when full catch (BoundedStack:overflow) /expected to throw stack.pop(); /pop() when full stack.pop()
15、; /pop() when partially-full try stack.pop(); /pop() when empty catch (BoundedStack:underflow) /expected to throw / destructor called implicitly at end of block;,其它覆盖率 基于状态的上下文覆盖,基于状态的上下文覆盖把一个状态上下文内的一个例行程序的执行认为是独立于另一个状态内相同例行程序的执行。为了达到100%的基于状态的上下文覆盖,例行程序必须在每个适当的上下文(状态)内被执行。基于状态的上下文覆盖率=(累加每个状态内执行到的方法
16、数)/(状态数类内方法总数),其它覆盖率 函数覆盖,有很多测试工具,例如TrueCoverage,PureCoverage等,都提供了函数覆盖的概念,函数覆盖是针对系统或一个子系统的测试的,它表示在该测试中,有哪些函数被测到了,其被测试到的频率有多大,这些函数在系统所有函数中占的比例有多大。函数覆盖是一个比较容易自动化的技术。函数覆盖=(至少被执行一次的函数数量)/(系统中函数的总数),缺陷:有些很大型的函数,只有其中一小部分被执行时,也算作被执行了,其它覆盖率 指令块覆盖,指令块覆盖(Instruction Blocks Coverage,IB Coverage)是语句覆盖的一个变体,其唯一
17、区别是计算方式的不同。在这里指令块覆盖表示函数内部的一个序列语句,在这一个序列语句中不存在控制语句(会引起分支)指令块覆盖=(至少被执行一次的指令块数量)/(系统中指令块总数),其它覆盖率 指令块覆盖举例,假定在一次测试过程中,在第一个控制点处走了3条指令的分支,在第二个控制点处走了空指令分支,那么其指令块覆盖是(2/4)*100%=50%,其语句覆盖是(5+3)/15*100%=53.33%,Instruction Blocks,其它覆盖率 判定路径覆盖,判定路径覆盖(Desition-to-Desition Paths Coverage,DDP Coverage)是判定覆盖的一个变体。这里的判定指的是一个序列语句,其起始位置是函数入口或一个判定(如if,while,switch等)的开始,结束位置是下一个判定的开始。DDP覆盖=(至少被执行到一次的判定路径数量)/(系统中判定路径的总数)判定路径覆盖和前面讲到的判定条件覆盖的思路是完全不同的:判定路径是一个独立的名词,而判定条件是两个独立的名词判定和条件构成的。,其它覆盖率 判定路径覆盖举例,