系列文章目录
文章目录
前言
- 白盒测试:结构测试或逻辑驱动测试
- 测试对象:程序的内部逻辑
- 静态白盒测试技术:代码检查、静态结构分析
- 动态白盒测试技术:程序插桩、逻辑覆盖、基本路径测试、域测试
【 第三章 白盒测试 】
3.1 逻辑覆盖
3.1.1 逻辑覆盖的类型
- 逻辑覆盖的类型:
- 语句覆盖:每条可执行语句
- 判定(分支)覆盖:每条分支路径
- 条件覆盖:每个判断的每个条件的所有可能取值
- 判定/条件覆盖:每个分支路径和每个判断的每个条件的所有可能取值
- 条件组合覆盖:每个判断的所有可能的条件取值组合
- 路径覆盖:每条可能的路径
- 只考虑整体:
- 语句覆盖:每条可执行语句
- 判定覆盖:每个判定的所有可能取值
- 路径覆盖:每条可能的路径
- 只考虑局部:
- 条件覆盖:每个判定中每个条件的所有可能取值
- 条件组合覆盖:每个判定所有可能的条件取值组合
- 兼顾整体局部:
- 判定/条件覆盖:同时满足判定覆盖和条件覆盖
- 逻辑覆盖的类型—语句覆盖
-
连锁选择结构:
-
优点:设计测试用例简单,可以很直观的从源代码得到测试用例,无须细分每条判定表达式
-
缺点:仅仅针对程序逻辑中显式存在的语句,但对于隐藏的条件和可能到达的隐式逻辑分支是无法预测的。因此语句覆盖对于多分支的逻辑运算时无法全面反映的
- 逻辑覆盖的类型—判定(分支)覆盖
-
同真同假
-
交叉取值
-
优点:
- 比语句覆盖具有更强的测试能力;
- 具有简单性,无须细分每个判定即可得到测试用例
-
缺点:
- 往往大部分的判定语句是由多个逻辑条件组合而成,若仅仅判断其最终结果,而忽略每个条件的取值情况,必然会遗漏部分测试路径
- 逻辑覆盖的类型—路径覆盖
- 逻辑覆盖的类型—条件覆盖
-
同真同假
-
交叉取值
-
优点:增加了对符合判定情况的测试,增加了测试路径
-
缺点:需要足够多的测试用例,但条件覆盖并不能保证分支覆盖。条件覆盖只能保证每个条件至少有一次为真,而不考虑所有的判定结果
- 逻辑覆盖的类型—条件组合覆盖
- 优点:同时满足判定覆盖、条件覆盖和判定/条件覆盖准则
- 缺点:线性的增加了测试用例的数量
- 逻辑覆盖的类型—判定/条件覆盖
- 优点:同时满足判定覆盖和条件覆盖准则,弥补了二者的不足
- 缺点:未考虑条件的组合情况
3.1.2 复杂情况分析
- 复杂情况分析——分支结构
- 当程序中判定多于一个时,形成的分支结构可以分为两类:嵌套型分支结构和连锁型分支结构
- 对于嵌套型分支结构,若有n个判定语句,需要n+1个测试用例;
- 对于连锁型分支结构, 若有n个判定语句,需要有2n个测试用例,覆盖它的2n条路径
- 复杂情况分析——简单循环
- 目标: 在循环内部及边界上执行测试
- 应重点测试的内容(n为循环最大次数):
- 零次循环(跳过循环)
- 一次循环:检查循环初始值
- 二次循环
- m次循环,其中2<m<n-1
- n-1,n和n+1次循环
3.复杂情况分析——嵌套循环
- 对最内层循环做简单循环的全部测试。所有其他层的循环变量置为最小值;
- 逐步外推,对其外面一层循环进行测试。测试时保持所有外层循环的循环变量取最小值,所有其他嵌套内层循环的循环变量取“典型”值。
- 反复进行,直到所有各层循环测试完毕。
- 对全部各层循环同时取最小循环次数,或者同时取最大循环次数。
4.复杂情况分析——串接循环
- 如果各个循环互相独立,则可以用与简单循环相同的方法进行测试。
- 但如果几个循环不是互相独立的,则需要使用测试嵌套循环的办法来处理。
5.复杂情况分析——不规则循环
- 不能进行测试
- 需要重新设计成结构化的程序后再进行测试
3.1.3 覆盖测试准则——Foster
- 【规则1】对于A rel B(rel为<、=和>)型的分支谓词,应适当选择A与B的值,使得测试执行到该分支语句时,A<B、A=B、A>B分别出现一次
- 【规则2】对于A rel1 C(rel1为<或>,A是变量,C是常量)型的分支谓词,当rel1为<时,应适当选择A的值,使A=C-M;同样,当rel1为>时,应适当选择A的值,使A=C+M
- 【规则3】对外部输入变量赋值,使其在每一测试用例中均有不同的值与符号,并与同一组测试用例中其他变量的值与符号不一致
3.2 基本路径测试
- 基本路径测试是在程序控制流图的基础上,通过分析控制构造的环路复杂性,导出基本可执行路径集合,从而设计测试用例的方法
- 在基本路径测试中,设计出的测试用例要保证在被测程序的每一条可执行语句上至少执行一次
3.2.1 基本路径测试的步骤
- 画出程序控制流程图
- 计算程序环路复杂性
- 确定独立路径集合
- 准备测试用例
(1) 画出程序控制流程图
- 结点:代表操作、条件判断及汇合点
- 控制流线或弧:控制的顺序
- 区域:弧与结点圈定的部分
- 重点:
- ① 复合条件下判定语句需拆分
- ② 控制流程图需保证每个条件结点出度等于2
- ③ 图的绘制保证单入口单出口
- ④ 根据情况适当增加汇合点
(2) 计算程序环路复杂性
- 计算程序复杂度的三种方法:
- 将程序复杂度定义为程序控制流图中的区域数
- 若设P为程序控制流图中的判定结点数,则有V(G)=P+1
- 设E为程序控制流图的边数,N为图的结点数,则定义程序的复杂度为V(G)=E-N+2
(3) 确定独立路径集合
- 独立路径是指从入口到出口的一条通路
- 和其他的独立路径相比,至少引入一个新处理语句(结点),或一条新的控制流线(弧)
- 程序的独立路径数 <= V(G)
(4) 准备测试用例
- ① 独立路径数≤环路复杂性
- ② 基本路径覆盖需保证结点和路径的覆盖
- ③ 独立路径需考虑不合理情况
3.2.2 复杂情况分析——分支结构
- 对于连锁型分支结构, 若有n个判定语句,需要有2n个测试用例,覆盖它的2n条路径
3.2.3 逻辑覆盖法&基本路径测试法
逻辑覆盖法
- 优点:
- ①依据真值表,节省测试工作工时
- ②六种覆盖准则,可适用于不同的应用场景
- 缺点:
①六种覆盖准则较为相似,易混淆
②无法兼顾效率及有效性
③未实现循环等复杂情况的真正简化
基本路径测试法
- 优点:
- ①测试数据基于单缺陷假设,提高了测试有效性
- ②将循环等复杂情况简化为与嵌套型分支结构相似的复杂度,大大提高了测试效率
- 缺点:
- ①依据程序控制流程图和独立路径分析设计测试用例,设计过程较为复杂
3.3 静态白盒测试技术
- 不运行被测程序本身而寻找程序代码中可能存在的错误或评估程序代码的过程
- 静态测试可采用手工或软件工具进行
- 静态测试工具的代表:
- Telelogic公司的LogiScope
- PR公司的PRQA
- McCabe公司的Quality ToolSet
3.3.1 代码检查法
- 代码检查法主要对以下内容进行检查:
- 检查代码和设计的一致性;
- 代码的可读性以及对软件设计标准的遵循情况;
- 代码逻辑表达的正确性;
- 代码结构的合理性;
- 程序中不安全、不明确和模糊的部分;
- 编程风格方面的问题等
代码检查法—桌面检查
- 程序设计人员对源程序代码进行分析、检查,并补充相关文档,发现程序中的错误
- 检查内容:变量,标号,子程序、宏、函数,等价性,常量,设计标准检查,风格检查,比较控制流,选择、激活路径,对照程序的规格说明,详细阅读源代码
- 效率极低
- 违反测试原则(可选择互审)
代码检查法—代码审查
- 数据引用错误(引用变量未初始化或赋值、数组下标范围和数据类型、指针引用单元的存在、指针类型与引用单元的数据类型不一致)
- 数据声明错误(是否明确声明、变量的属性没有声明使用默认属性、变量初始化、变量赋予正确的长度和数据类型、是否存在相似名称的变量)
- 运算错误(不一致类型的运算、混合模式运算、表达式的溢出、除数为0、运算符的优先级)
- 比较错误(不同数据类型、混合转换规则、比较运算符是否正确、与或非)
- 控制流程错误(循环是否都能终止、程序模块子程序是否都能终止、循环初始条件)
- 接口错误(形参和实参的对应、输入和输出参数)
- 输入/输出错误(打开文件属性、足够可用内存空间、文件的打开关闭)
- 其他检查(系统警告或提示信息、对输入合法性进行检查、程序是否遗漏了功能)
代码检查法—走查
- 人员组成:由程序设计人员和测试人员组成5人审查小组
- 资深程序员、有程序经验的测试人员、没有介入项目的新人
- 形式:通过逻辑运行程序查找错误
- 审查期间活动:依据测试用例数据逻辑运行程序,并把程序的状态(如变量的值)记录在纸张或白板上以供监视
代码检查法—技术评审
- 人员组成:由开发组、测试组和相关人员(QA、产品经理等)联合进行
- 形式:综合运用走查、审查技术,逐行、逐段的检查软件
- 技术评审与走查和审查的不同之处在于表述代码的表述者
- 检查要点是设计需求、代码标准/规范/风格和文档的完整性与一致
代码检查法—总结
- 优点:
- ①一旦发现错误,即可在代码中精确定位,降低调试的成本;
- ②还可发现成批的错误
- 效果:通常是能够有效地查找出30%-70%的逻辑设计和编码错误,但不能有效地查找出高层次的设计错误,且耗费时间较多
- 地位:是与计算机的测试互补的
3.3.2 代码编程规范检查
- 编码规范又称代码规则、编码规则
- 是对程序代码的格式、注释、标识符命名、语句使用、函数、类、程序组织、公共变量等方面的要求
- 遵循编程规范的好处:
- 开发人员书写的代码更健壮、更安全、更可靠
- 提高代码的可读性,使代码易于查看、理解和维护
- 提高代码质量最有效、最直接的手段
3.3.3 静态结构分析法
静态结构分析法—生成图表
- 常用引用表:
- 标号交叉引用表
- 变量交叉引用表
- 子程序(宏、函数)引用表
- 等价表
- 常数表
- 常用关系图、控制流图:函数调用关系图和模块控制流图
静态结构分析法—静态错误分析
- 主要用于确定在源程序中是否有某类错误或“危险”结构
- 类型和单位分析
- 引用分析
- 表达式分析
- 接口分析
静态结构分析法—总结
- 主要问题:
- 程序层次性较差
- 存在直接和间接的递归调用
- 重要资源被众多模块使用
3.4 其他白盒测试方法
3.4.1 程序插桩
程序插桩—方法简介
-
向源程序中添加一些语句,实现对程序语句的执行、变量的变化等情况进行检查
-
了解一个程序在某次运行中所有可执行语句被覆盖的情况,或是每个语句的实际执行次数
-
计算整数X和整数Y的最大公约数程序
-
设计插桩程序时需要考虑的问题:
- 探测哪些信息;
- 在程序的什么部位设置探测点;
- 程序块的第一个可执行语句之前
- 有标号的可执行语句处
- Do、Do While、Do Until、for等循环语句处
- If、ElseIf、Else及End If等条件语句各分支处
- 输入/输出语句之后
- 函数、过程、子程序调用语句之后
- Return语句之后
- Goto语句之后
- 需要设置多少个探测点;
- 如何在程序中特定部位插入某些用以判断变量特性的语句。
程序插桩—断言语句
- 在程序的特定部位插入某些用以判断变量特性的语句,使得程序执行中这些语句得以证实,从而使程序的运行特性得以证实
- 这些语句称为断言(assertions)
3.4.2 域测试
域测试—方法简介
- 域测试是一种基于程序结构的测试方法
- Howden对程序中出现的错误分类:
- 如果程序的控制流有错误,对于某一特定的输入可能执行的是一条错误路径,这种错误称为路径错误,也叫做域错误
- 如果对于特定输入执行的是正确路径,但由于赋值语句的错误致使输出结果不正确,则称此为计算型错误
- 程序某处缺少判定谓词引起的错误是丢失路径错误
- 域测试方法基于对输入空间的分析
- 测试的理想结果就是检验输入空间中的每一个输入元素是否都产生正确的结果
- 输入空间可分为不同的子空间,子空间的划分是由程序中分支语句的谓词决定的
- 域测试正是在分析输入域的基础上,选择适当的测试点以后进行测试的
域测试—输入域结构
域测试—测试点的选择
- 测试点的选择:
- ON点:位于域的边界上
- OFF点:离边界有一个小距离ε,并在被测域之外
- 如果将ON点与OFF点交替选择,即让OFF点在两个ON点所决定直线上的投影在ON点之间,可较好的测出由于边界错误导致的域错误
- 错误边界距离正确边界相差不大的情况称为边界位移
- 边界位移错误、谓词中运算符错误
3.5 白盒测试策略
- 在测试中,应尽量先使用自动化工具进行静态结构分析
- 测试中可采取先静态后动态的组合方式:先进行静态结构分析、代码检查,再进行覆盖率测试
- 利用静态分析的结果作为引导,通过代码检查和动态测试的方式对静态分析结果做进一步的确认,使测试工作更为有效
- 一般可使用基本路径测试法达到独立路径的覆盖准则;对于软件的重点模块,应使用多种覆盖率标准衡量测试的覆盖率
- 在不同测试阶段,测试的侧重点不同
- 单元测试阶段,以代码检查、逻辑覆盖为主
- 集成测试阶段,需增加静态结构分析
- 系统测试阶段,应根据黑盒测试的结果,采取相应的白盒测试方法
3.6 黑盒测试与白盒测试的比较
- 白盒与黑盒这两类测试是从完全不同的角度出发看待测试对象的
- 白盒测试只考虑测试软件产品,不保证完整的需求规格是否被满足;而黑盒测试只考虑需求规格,不保证实现的所有部分是否被测试到
- 黑盒测试会发现遗漏的缺陷,指出规格的哪些部分没有被完成;而白盒测试会发现提交的缺陷,指出哪些实现的部分是错误的
- 白盒测试的成本比黑盒测试高得多。它需要在测试可以被计划之前先有源代码
- 一个白盒测试的失败会导致一次修改,这需要所有的黑盒测试被重复执行并且重新决定白盒测试路径
白盒测试の优缺点
- 白盒测试的优点:
- 迫使测试人员去仔细思考软件的实现
- 可以检测代码中的每条分支和路径
- 揭示隐藏在代码中的错误
- 对代码的测试比较彻底
- 最优化
- 白盒测试的缺点:
- 昂贵
- 无法检测源代码中遗漏的路径和数据敏感性错误
- 不验证规格的正确性
黑盒测试の优缺点
- 黑盒测试的优点:
- 对于较大的代码单元(子系统或系统级),黑盒测试比白盒测试效率要高
- 测试人员不需要了解实现的细节,包括特定的编程语言
- 测试人员和编码人员是彼此独立的
- 从用户的视角进行测试,很容易被理解和接受
- 有助于暴露任何规格不一致或有歧义的问题
- 测试用例可以在规格说明完成后马上作出来
- 黑盒测试的缺点:
- 只有一小部分可能的输入被测试到,要测试每个可能的输入流几乎是不可能的
- 若没有清晰和简明的规格说明,测试用例很难设计
- 会有很多程序路径没被测试到
- 不能直接针对特定程序(模块)测试,这些程序可能很复杂(因此可能隐藏更多的问题)
3.7 程序结构分析
3.7.1 控制流分析
控制流分析—控制流图
控制流分析—程序结构的基本要求
- 不应包含的情况:
- 转向并不存在的标号
- 没有用的语句标号
- 从程序入口无法到达的语句
- 不能达到停机语句的语句
3.7.2 数据流分析
数据流分析—数据流问题
- 变量被语句定义:某一语句执行时能改变变量V的值,则称V是被该语句定义的
- 变量被语句引用:某一语句的执行引用了内存变量V的值,则称变量被语句引用
- 语句:X:=Y+Z定义了变量X, 引用了Y, Z
- 语句:if Y>Z then …引用了Y和Z
- 语句:READ X 定义了X
- WRITE X 引用了X
- 语句的执行也可以使变量失去定义,成为无意义
总结
- 掌握逻辑覆盖和基本路径测试的方法和技术
- 了解静态白盒测试技术
- 熟悉程序插桩、域测试等其他动态白盒测试技术的基本思想
- 理解白盒测试和黑盒测试之间的区别