软件测试课程软件白盒测试概览在本章中,我们将学习:–结构性白盒测试概述–程序结构分析–逻辑覆盖–结构性测试案例目标完成此课程之后,学员将具备以下能力:–了解结构性测试的含义–进行程序结构分析–使用逻辑覆盖的方法进行白盒测试–了解白盒测试工具课程目录结构测试概述程序结构分析逻辑覆盖结构测试案例分析结构测试工具结构测试定义把测试对象看做一个透明的盒子白盒测试是根据被测程序的内部结构设计测试用例并完成测试的一种测试方法白盒测试或逻辑驱动测试基于一个应用代码的内部逻辑知识,测试覆盖全部代码、分支、路径和条件结构测试特点可以构成测试数据使特定程序部分得到测试有一定的充分性度量手段可获得较多工具支持通常只用于单元测试结构测试的方法静态测试方法:程序结构分析–代码走查–代码审查–控制流分析–数据流分析–信息流分析动态测试方法:逻辑覆盖–语句覆盖–分支覆盖–条件覆盖–分支-条件覆盖–路径覆盖代码覆盖率采用白盒法进行测试时,考虑的是测试用例对程序内部逻辑的覆盖程度最彻底的白盒法是覆盖程序中的每一条路径,但这往往无法实现采用其它一些标准来量度覆盖的程度,并希望覆盖程度尽可能高些课程目录结构测试概述程序结构分析逻辑覆盖结构测试案例分析结构测试工具使用程序结构分析代码走查代码审查控制流分析数据流分析信息流分析代码走查含义–代码走查是由一组程序和错误检查技术组成,并以代码审查组方式进行人员–组长(有威信的资深程序员担任):负责分配资料、安排计划、主持会议、记录并保存被发现的错误–资深程序员–测试人员–程序开发员(可做会议主持)重点探讨代码编写思路:比如算法,基于对象的编程,类设计。但是代码走查非常枯燥,现在变成了关注于强制代码标准代码审查内容–检查代码和设计的一致性–检查代码对标准的遵循、可读性–检查代码的逻辑表达的正确性–检查代码结构的合理性–形成公司积累变成容易出错的checklist代码审查步骤–准备–程序阅读–审查会–跟踪及报告控制流分析非结构化程序会给测试、排错、和程序的维护带来许多困难要求写出的程序结构良好检查程序的控制结构成为十分有意义的工作程序流程图1325控制流图12435abcdef控制流图节点–标有编号的圆圈–程序流程图中矩形框所表示的处理–菱形表示的两个甚至多个出口判断–多条流线相交的汇合点控制流图控制流线或弧–箭头–与程序流程图中的流线一致,表明了控制的顺序–控制流线通常标有名字控制流图矩阵acbdef1234512345控制流图矩阵便于机器表示和处理控制流图连接弧的节点的号码决定了矩阵中元素的位置注意控制流的方向(行--〉列)两个节点没有弧线,所对应的位置也就没有元素程序结构的基本要求写出的程序不应包含:–转向并不存在的标号–没有用的语句标号–从程序入口进入后无法达到的语句–不能达到停机语句的语句–目前对这四种情况的检测主要通过编译器和程序分析工具来实现。–可以利用控制流图分析出来,是否存在以上情况。–例如:1-》2-》3、4-》4-》5(结束)数据流分析查找引用未定义变量等程序错误查找对以前未曾使用的变量再次赋值等数据流异常的情况常见的错误表现形式–错拼名字–名字混淆–语句丢失数据流如果程序中某一语句执行时能改变某程序变量V的值,则称V被该语句定义如果一语句的执行引用了内存中变量V的值,则称V被该语句引用例如:–X=Y+Z;---------X被定义,Y和Z被引用–ifYZthenreturn;----Y和Z被引用控制流图与数据流表1234106758911节点被定义变量被引用变量1X,Y,Z2XW,X3X,Y4Y,Z5YV,Y6ZV,Z7VX8WY9ZV10ZZ11ZZ的值被送给外部环境例如:假定某个变量的值在使用以前被错误的改写了(对输出没有任何作用),这个语句就会被发现信息流分析通过对输入数据、输出数据、语句之间的关系的分析来检查程序错误信息流分析用来分析,是否存在无用的语句。整除算法例子输入:in_m是被除数,in_n是除数输出:out_q是商,out_r是余数整除算法例子1out_q=0;2out_r=in_m;3While(out_r=in_n){4out_q++;5out_r=out_r–in_n;}信息流关系图√√√√√√√in_min_n12345√√√√√√√√out_qout_r12345√√√√out_qout_rin_mIn_n(1)输入变量影响语句(2)语句影响到输出变量(3)输入影响到输出信息流分析能够列出对输入变量的所有可能的引用在程序的任何指定点检查其执行可能影响某一输出变量值的语句输入输出关系提供一种检查,看每个输出值是否由相关的输入值,而不是其他值导出课程目录白盒测试概述程序结构分析逻辑覆盖结构测试案例分析结构测试工具使用覆盖准则测试到什么地步可以结束测试?–覆盖准则被测小程序if(A1&&B==0)X=X/A;if(A==2||X1)X=X+1;被测程序段流程图A1&&B==0aA==2||X1X=X/AFTbcX=X+1TeFd逻辑覆盖测试方法语句覆盖分支覆盖条件覆盖分支-条件覆盖路径覆盖语句覆盖原理:如果语句中有错误,仅靠观察不执行可能发现不了在测试时,首先设计若干个测试用例,然后运行被测程序,使程序中的每个可执行语句至少执行一次语句覆盖、程序段覆盖、程序块覆盖语句覆盖率语句覆盖率–已执行的可执行语句占程序中可执行语句总数的百分比复杂的程序不可能达到语句的完全覆盖语句覆盖率越高越好语句覆盖测试用例达到语句覆盖100%的测试用例(路径ace)A=2B=0X=3未达到语句覆盖100%的测试用例(路径abe)A=2B=1X=3语句覆盖的优点检查所有语句结构简单的代码的测试效果较好容易实现自动测试代码覆盖率高如果是程序块覆盖,则不涉及程序块中的源代码语句覆盖不能检查出的错误条件语句错误–“A1&&B==0”-“A0&&B==0”逻辑运算(&&、||)错误–“A1&&B==0”-“A1||B==0”–“U=A1||B2”-“U=A1”语句覆盖不能检查出的错误循环语句错误–循环次数错误–跳出循环条件错误语句覆盖不能检查出的错误循环语句例子for(i=0;i10;i++){statement;}While(x3){statement;}for(i=0;i=10;i++){statement;}While(x3&&x7){statement;}语句覆盖率的问题能达到很高的语句覆盖率语句覆盖率看似很高,却有严重缺陷if(x!=1){statements;……;}else{statement;}}99句}1句测试用例x=2语句覆盖率99%50%的分支没有达到分支覆盖设计若干测试用例,运行被测程序,使得程序中每个判断的真假分支至少经历一次又称判定覆盖while语句、switch语句、异常处理、跳转语句等等同样可以使用分支覆盖来测试分支覆盖率–已取过“真”和“假”两个值的判定占程序中所有条件判定个数的百分比分支覆盖测试用例路径aceA=2B=0X=3路径abdA=1B=0X=1路径acdA=3B=0X=3路径abeA=2B=1X=2或分支覆盖的利弊分支覆盖要比语句覆盖查错能力强一些:执行了分支覆盖,实际也就执行了语句覆盖分支覆盖与语句覆盖存在同样的缺点–不能查出条件语句错误–不能查出逻辑运算错误–不能查出循环次数错误–不能查出循环条件错误条件覆盖设计若干测试用例,执行被测程序以后,要使每个判断中的每个条件的可能取值至少满足一次条件覆盖分析第1个判断应考虑A1,记为T1A=1,即记为F1B==0,记为T2B!=0,记为F2第2个判断应考虑A==2,记为T3A!=2,记为F3X1,记为T4X=1,记为F4条件覆盖测试用例用例编号ABX路径覆盖条件1203aceT1,T2,T3,T42101abdF1,T2,F3,F43211abeT1,F2,T3,F4似乎执行了条件覆盖必然实现了分支覆盖?条件覆盖测试用例用例编号ABX路径覆盖条件1103abeF1,T2,F3,T42211abeT1,F2,T3,F4执行条件覆盖并不能实现分支覆盖条件覆盖的利弊能够检查所有的条件错误不能实现对每个分支的检查用例数量的增加–a&&b&&(c||(d&&e))–((a||b)&&(c||d))&&e分支-条件覆盖设计足够的测试用例,使得判断中每个条件的所有可能至少出现一次,并且每个判断本身的判定结果也至少出现一次分支-条件覆盖分析(1)A1,B==0,记为T1,T2(2)A1,B!=0,记为T1,F2(3)A=1,B==0,记为F1,T2(4)A=1,B!=0,记为F1,F2(5)A==2,X1,记为T3,T4(6)A==2,X=1,记为T3,F4(7)A!=2,X1,记为F3,T4(8)A!=2,X=1,记为F3,F4分支-条件覆盖测试用例用例编号ABX覆盖组合号路径覆盖条件1203(1)(5)aceT1,T2,T3,T42211(2)(6)abeT1,F2,T3,F43103(3)(7)abeF1,T2,F3,T44111(4)(8)abdF1,F2,F3,F4覆盖了3条路径,漏掉了路径acd分支-条件覆盖的利弊既考虑了每一个条件,又考虑了每一个分支,发现错误能力强于分支覆盖和条件覆盖并不能全面覆盖所有路径用例数量的增加路径覆盖设计足够多的测试用例,要求覆盖程序中所有可能的路径路径–ace记为L1–abd记为L2–abe记为L3–acd记为L4路径覆盖测试用例用例编号ABX覆盖路径1203ace(L1)2101abd(L2)3211abe(L3)4301acd(L4)基本路径测试方法路径测试就是从一个程序的入口开始,执行所经历的各个语句的完整过程。从广义的角度讲,任何有关路径分析的测试都可以被称为路径测试。完成路径测试的理想情况是做到路径覆盖,但对于复杂性大的程序要做到所有路径覆盖(测试所有可执行路径)是不可能的。在不能做到所有路径覆盖的前提下,如果某一程序的每一个独立路径都被测试过,那么可以认为程序中的每个语句都已经检验过了,即达到了语句覆盖。这种测试方法就是通常所说的基本路径测试方法。基本路径测试方法(续)基本路径测试方法是在控制流图的基础上,通过分析控制结构的环形复杂度,导出执行路径的基本集,再从该基本集设计测试用例。基本路径测试方法包括以下4个步骤:(1)画出程序的控制流图。(2)计算程序的环形复杂度,导出程序基本路径集中的独立路径条数,这是确定程序中每个可执行语句至少执行一次所必须的测试用例数目的上界。(3)导出基本路径集,确定程序的独立路径。(4)根据(3)中的独立路径,设计测试用例的输入数据和预期输出。环形复杂度环形复杂度也称为圈复杂度,它是一种为程序逻辑复杂度提供定量尺度的软件度量。环形复杂度的应用——可以将环形复杂度用于基本路径方法,它可以提供:程序基本集的独立路径数量;确保所有语句至少执行一次的测试数量的上界。独立路径是指程序中至少引入了一个新的处理语句集合或一个新条件的程序通路。采用流图的术语,即独立路径必须至少包含一条在本次定义路径之前不曾用过的边。测试可以被设计为基本路径集的执行过程,但基本路径集通常并不唯一。计算环形复杂度的方法环形复杂度以图论为基础,为我们提供了非常有用的软件度量。可用如下三种方法之一来计算环形复杂度:控制流图中区域的数量对应于环形复杂度。给定控制流图G的环形复杂度—V(G),定义为V(G)=E-N+2其中,E是控制流图中边的数量,N是控制流图中的节点数量。给定控制流图G的环形复杂度—V(G),也可定义为V(G)=P+1其中,P是控制流图G中判定节点的数量。判定节点是输出边至少2条以上的节点。基本路径测试方法(续)voidSort(intiRecordNum,int