第7章04 白盒测试及用例生成
6.1 白盒测试概述
白盒测试又称结构测试、逻辑驱动测试、基于程序的测试。
课件指出“白盒测试 = 结构化测试”。
白盒测试定义:一种基于源程序或代码的测试方法,依据源程序或代码结构与逻辑生成测试用例,以尽可能多地发现并修改源程序错误。
白盒测试两个特点:
- 基于代码;
- 尽可能覆盖实现的行为。
黑盒测试两个特点:
- 基于规约;
- 尽可能覆盖定义的行为。
为什么需要白盒测试?
- ==确保每段代码都被执行==,避免相应缺陷;
- 是黑盒测试 / 功能测试的==补充==;
- 能覆盖高层规范说明中忽视的==底层细节==;
- 更容易进行==自动化==测试。
6.2 静态白盒测试与动态白盒测试
动态白盒测试流程:
- 构造程序图,如 CFG、PDG;
- 生成测试用例;
- 执行测试;
- 分析覆盖标准;
- 判定测试结果。
动态白盒测试方法:
- 基于控制流的方法;
- 基于数据流的方法。
静态白盒测试
静态白盒测试是在不执行软件的条件下,有条理地仔细审查软件设计、体系结构和代码,从而找出软件缺陷的过程,有时称为结构化分析。
实施静态白盒测试的理由
- 尽早发现软件缺陷;
- 为后继测试中设计测试用例提供思路。
静态白盒测试可以更早、更低成本地发现缺陷。
静态白盒测试优点
- 可发现某些机器发现不了的错误;
- 利用不同人对代码的不同观点;
- 对照设计,确保程序能完成预期功能;
- 不但能检测出错误,还可以尝试确定错误根源;
- 节约计算机资源,但以增加人工成本为代价;
- 尽早发现缺陷,避免后期缺陷修复造成巨大压力。
易错点
- 静态白盒测试不一定节省人工成本,它通常会增加人工成本;
- 但它能节约计算机资源,并减少后期修复压力。
静态白盒测试具体方法
- 技术评审 technical review;
- 代码 / 文档阅读 code/document reading;
- 走查 / 通查 walk through;
- 专项检查 inspection;
- 代码 / 数据 / 文档审计 code/data/document audit。
动态白盒测试
覆盖标准
覆盖标准的意义:覆盖标准是对“测试执行到何时才是充分的?”这个问题的定量回答。
覆盖标准的作用:作为测试软件的一种度量标准,描述程序源代码被测试的程度。
重要结论:一种测试技术通常有一种对应的覆盖标准。
6.3 控制流测试
白盒测试要求对被测程序结构特性达到一定程度覆盖。
课件中还强调:路径覆盖是一种较强覆盖标准,但不能替代条件覆盖和条件组合覆盖。
语句覆盖(所有节点覆盖)
语句覆盖 Statement Coverage 是指选择足够的测试用例,使得运行这些测试用例时,被测程序的每条可执行语句都至少执行一次。
语句覆盖是最弱的逻辑覆盖准则之一。
即使达到 100% 语句覆盖,也可能发现不了严重问题。
判定覆盖(分支覆盖/所有边覆盖)
判定覆盖 Decision Coverage,也称分支覆盖,是指选择足够的测试用例,使得运行这些测试用例时,被测程序的每个判定的所有可能结果都至少执行一次。(每个判断至少获得一次 True 和一次 False。)
优点
- 简单;
- 包含语句覆盖;
- 避免了部分语句覆盖的问题。
判定覆盖包含语句覆盖并避免了语句覆盖的问题
条件覆盖
条件覆盖保证每个判断中的每个条件的取值至少满足一次。
测试用例需要让每个原子条件都至少取到一次 True 和 False。
条件覆盖不能保证程序所有分支都被执行。
判定条件覆盖
判定条件覆盖要求每个判定的所有可能结果至少执行一次,并且每个判定中的每个条件的所有可能结果也至少出现一次。
也就是同时满足:
- 判定覆盖;
- 条件覆盖。
错误屏蔽是指原子条件取值改变不会影响判定结果,因此该条件上的取值错误是不可见的。
条件组合覆盖
情形1:每个判定中条件的各种可能组合至少出现一次
两个条件共有四种组合:
- T OR T;
- T OR F;
- F OR T;
- F OR F。
情形2:所有条件的所有可能取值组合至少出现一次
如果程序中有 n 个原子条件,则组合数可能是:$$ 2^n $$
条件组合覆盖很强,但:
- 组合数可能指数级增长;
- 某些条件组合不存在;
- 仍可能出现错误屏蔽;
- 不一定覆盖所有路径。
路径覆盖
路径覆盖 Path Coverage 是指选择足够的测试用例,保证每条可能执行到的路径都至少经过一次。
路径覆盖实际上考虑了程序中各种判定结果的所有可能组合,但它未必能覆盖判定中条件结果的各种可能情况。
路径覆盖是一种比较强的覆盖标准,但不能替代条件覆盖和条件组合覆盖。

6.4 基本路径测试(基于控制流)
基本路径测试思想:寻找==基本路径==,根据基本路径构造测试用例,保证每条基本路径至少执行一次。
测试用例设计过程:源程序 / PDL → 控制流图 CFG → 圈复杂度 → 基本路径 → 测试用例
控制流图 CFG
控制流图用于描述程序中的逻辑控制流:
- 节点:语句或基本块;
- 边:控制流。
基本路径
基本路径,又称独立程序路径,是指任何一条贯穿程序的路径,该路径至少包含一条不同于其他路径的边。
- 基本路径集合中路径条数唯一,但基本路径集合本身可以不唯一;
- 其他路径可以通过基本路径运算得到;
- 基本路径集合大小由圈复杂度确定。
课件强调两个核心特性:
- 基本路径集合中路径条数唯一,但基本路径可以不一样。
- 其他路径可以通过基本路径运算得到。
圈复杂度——基本路径的度量
圈复杂度度量基本路径数,是所有语句被执行一次所需测试用例数的上限之一,即执行所有基本路径即可实现100%语句覆盖
基本路径覆盖不等于分支覆盖。
基本路径测试与第6章圈复杂度相连:
$$ V(G)=E-N+2P $$
单连通 CFG 常用:
$$ V(G)=E-N+2 $$
也可用:
$$ V(G)=J+1 $$
其中 $J$ 是判定节点数。
主观题答题步骤:
- 根据代码或 PDL 画 CFG。
- 标出节点和边。
- 计算圈复杂度,确定基本路径条数。
- 列出一组基本路径集合。
- 为每条基本路径设计测试用例。
注意:课件明确指出“基本路径覆盖 != 分支覆盖”,但也给出“基本路径覆盖 -> 分支覆盖”方向关系。答题时不要简单互换。
循环处理(基于控制流)
课件将循环分为四种:
- 简单循环;
- 嵌套循环;
- 串接循环;
- 非结构循环。
1.简单循环测试
对简单循环,应构造以下测试用例:
- 跳过整个循环,即执行 0 次循环;
- 只执行 1 次循环;
- 执行 2 次循环;
- 执行 m 次循环,其中 $m<n$;
- 执行 $n-1$、$n$、$n+1$ 次循环。
其中 n 表示循环允许的最大次数。
适用边界值测试的 $6n+1$ 公式。
2.嵌套循环测试
- 先测试最内层循环:
- 所有外层循环变量置为最小值;
- 最内层按==简单循环测试==。
- 由里向外,测试上层循环:
- 此层以外的所有外层循环变量取最小值;
- 此层以内的所有嵌套内层循环变量取典型值;
- 当前层按简单循环测试。
- 重复上一条规则,直到所有层循环测试完毕。
- 对全部各层循环同时取最小循环次数,或者同时取最大循环次数。
记忆点
嵌套循环测试顺序:
先内后外,外层取最小,内层取典型。
3.串接循环测试
串接循环分两种情况。
情况1:各循环互相独立
如果串接的各个循环互相独立:
分别用简单循环的方法进行测试。
情况2:循环之间不独立
如果两个循环不独立,例如第一个循环变量与第二个循环控制相关:
把第一个循环看作外循环,第二个循环看作内循环,用嵌套循环方法处理。
4.非结构循环测试
非结构循环应该先将其结构化,然后再测试。重复编码法。
6.5 数据流测试
定义
数据流是变量的定义或使用顺序和变量可能状态的一种描述。变量状态可以是创建/定义、使用、清除/销毁等。
数据流测试是一种面向变量定义位置到使用位置覆盖的基于程序结构的测试方法,重点关注变量的定义与使用。
它重点关注:
- 变量在哪里被定义;
- 变量在哪里被使用;
- 从定义到使用之间变量值如何变化;
- 是否存在与变量定义和使用相关的 Bug。
可发现的问题
- 变量未初始化就被读取;
- 变量定义后从未使用;
- 变量被错误赋值;
- 定义和使用之间路径异常。
与路径测试区别
课件指出:数据流测试可认为是路径测试的“真实性”检查,是对路径测试的一种改良。
数据流测试基本思想
程序是对数据的加工处理过程,因此可以从数据处理流程角度进行测试。
数据处理流程对应:数据流图 DFG。
数据流图类似控制流图 CFG,但更详细描述变量的:
- 创建;
- 使用;
- 销毁。
数据流测试步骤:
- 对给定程序构造数据流图;
- 找出所有变量的定义-使用路径;
- 考察测试用例对这些路径的覆盖程度,作为衡量测试效果的度量值。
基本概念
1. P:P 表示程序。
2. G(P):G(P) 表示程序 P 的数据流图。
3. V:V 表示变量集合。
例如课件示例程序中: $$ V={staffDiscount,\ totalPrice,\ finalPrice,\ discount,\ price} $$ 4. PATH(P):PATH(P) 表示程序 P 的所有路径集合。
数据流测试步骤
课件步骤:
- 对给定程序构造程序数据流图;
- 找出所有变量的定义-使用路径。
- 考察测试用例对这些路径的覆盖程度,即可作为衡量测试效果的度量值。
考试可展开为:
- 标出每个变量的定义节点 DEF;
- 标出每个变量的使用节点 USE,并区分 P-use 与 C-use;
- 枚举可能的 DU 路径;
- 去除不满足定义清洁的路径;
- 根据覆盖准则选择路径;
- 为路径设计测试用例。
Rapps-Weyuker 覆盖标准
目标包括:
- 保证所选路径数目总是有限的 / 可被实际处理的;
- 寻找系统化的测试路径选择方案,以帮助发现未知缺陷。
第二次小测已考。
课件还列出 Ntafos、Ural、Laski-Korel 标准,但本次文本重点展开的是 Rapps-Weyuker 九条。
数据流测试优点和缺点
优点
- 揭示隐藏在代码变量定义和使用中的各种错误;
- 可以覆盖所有语句、所有分支、所有路径;
- 对代码测试比较彻底。
缺点
- 无法检测代码中不可达路径;
- 不验证需求规格。
6.6 数据流测试主观题模板
如果题目给代码片段或流程图:
- 画或整理 CFG/DFG。
- 对每个变量分别列 DEF 节点。
- 对每个变量分别列 USE 节点,并标注 P-use/C-use。
- 枚举 DEF 到 USE 的候选路径。
- 删除非定义清洁路径。
- 按题目要求选择 All-Defs、All-Uses 或 All-DU-Paths 等标准。
- 写测试路径和测试数据。
常见扣分点:
- 把变量定义和使用混淆;
- 不区分谓词使用和计算使用;
- DU 路径中间又重新定义了变量,却仍当成有效 DU 路径;
- 只写路径,不写测试用例。
6.7 白盒测试主观题方法总表
6.8 小测关联
第二次小测已考:
- 结构化测试包括控制流测试和数据流测试;
- 数据流覆盖标准包括 All-Paths、All-Edges、All-Nodes、All-Defs、All-P-Uses、All-P-Uses/Some C-Uses、All-C-Uses/Some P-Uses、All-Uses、All-DU-Paths;
- 黑盒与白盒辨析。
6.9 本章复习检查题
填空题
- 白盒测试又称________测试、逻辑驱动测试、基于程序的测试。
- 数据流测试重点关注变量的________与________。
- P-use 是________使用,C-use 是________使用。
选择题
- 保证每个判断 True 和 False 至少一次的是:A. 语句覆盖 B. 判定覆盖 C. 条件覆盖 D. All-Defs
- All-Nodes 等价于:A. 语句覆盖 B. 分支覆盖 C. 路径覆盖 D. 条件组合覆盖
判断题
- 条件覆盖一定能保证所有分支都被执行。
- 数据流测试可以发现定义-使用异常。
- 基本路径集合中路径条数由圈复杂度确定。
参考答案
- 填空:结构;定义、使用;谓词、计算。
- 选择:B;A。
- 判断:错;对;对。
第7章04 客观题必背清单
A. 填空题重点
- 白盒测试等价于结构化测试。
- 白盒测试两个特点:基于代码、尽可能覆盖实现的行为。
- 黑盒测试两个特点:基于规约、尽可能覆盖定义的行为。
- 白盒测试又称结构测试、逻辑驱动测试、基于程序的测试。
- 白盒测试分为静态白盒测试和动态白盒测试。
- 静态白盒测试是在不执行软件的条件下审查设计、体系结构和代码。
- 静态白盒测试方法包括技术评审、代码/文档阅读、走查、专项检查、审计。
- 动态白盒测试需要源代码和可执行程序,并需要执行程序。
- 覆盖标准是对“测试执行到何时才充分”的定量回答。
- 控制流覆盖测试包括语句覆盖、判定覆盖、条件覆盖、判定条件覆盖、条件组合覆盖、路径覆盖。
- 语句覆盖要求每条可执行语句至少执行一次。
- 判定覆盖又称分支覆盖,要求每个判定 True 和 False 至少一次。
- 条件覆盖要求每个判定中的每个条件取值至少满足一次。
- 判定条件覆盖同时要求判定结果和条件结果都覆盖。
- 条件组合覆盖要求条件取值组合至少出现一次。
- 路径覆盖要求每条可能执行路径至少执行一次。
- 基本路径又称独立程序路径。
- 圈复杂度可用 $V(G)=E-N+2$ 计算。
- 圈复杂度也等于判定结点数 + 1。
- 圈复杂度也等于区域数量。
- 简单循环测试包括 0、1、2、m、n-1、n、n+1 次。
- 数据流测试面向变量定义位置、使用位置覆盖。
- DEF(v,n) 表示在节点 n 定义变量 v。
- USE(v,n) 表示在节点 n 使用变量 v。
- P-use 是谓词使用,C-use 是计算使用。
- DU-path 是定义-使用路径。
- DC-path 是定义-清洁路径。
- All-Paths 等价于路径覆盖。
- All-Edges 等价于分支覆盖。
- All-Nodes 等价于语句覆盖。
- All-Defs 要求每个变量每个定义至少到达某个使用。
- All-Uses 要求每个定义到每个使用至少一条 dc-path。
- All-DU-Paths 要求每个定义到每个使用的所有 dc-path。
B. 选择题重点
C. 判断题易错点
第7章04 主观题可能考法
情景1:给代码或流程图,判断覆盖准则
答题模板:
- 找出所有语句;
- 找出所有判定;
- 找出每个判定中的原子条件;
- 根据题目要求判断:
- 语句覆盖:是否每条语句执行;
- 判定覆盖:每个判定 True/False 是否覆盖;
- 条件覆盖:每个条件 True/False 是否覆盖;
- 判定条件覆盖:判定和条件是否都覆盖;
- 条件组合覆盖:条件组合是否全覆盖;
- 路径覆盖:路径是否全覆盖。
情景2:给程序,要求基本路径测试
答题模板:
- 画控制流图 CFG;
- 统计边数 E、结点数 N,或统计判定结点 P;
- 计算圈复杂度: $$ V(G)=E-N+2 $$ 或: $$ V(G)=P+1 $$
- 确定基本路径数量;
- 列出基本路径集合;
- 为每条基本路径设计测试用例;
- 写出预期输出。
情景3:给循环结构,设计循环测试用例
答题模板:
- 判断循环类型:
- 简单循环;
- 嵌套循环;
- 串接循环;
- 非结构循环。
- 简单循环测:
- 0次;
- 1次;
- 2次;
- m次;
- n-1、n、n+1次。
- 嵌套循环:
- 先测最内层;
- 外层取最小;
- 内层取典型;
- 由里向外测试。
- 串接循环:
- 独立则分别测;
- 不独立则按嵌套循环处理。
- 非结构循环:
- 先结构化,再测试。
情景4:给代码片段,要求数据流测试
答题模板:
- 写出变量集合 V;
- 对指定变量 v 找定义节点 DEF(v,n);
- 找使用节点 USE(v,n);
- 判断使用类型:
- P-use;
- C-use;
- O-use;
- L-use;
- I-use。
- 列出 DU-path;
- 判断哪些是 DC-path;
- 根据覆盖准则选择测试路径;
- 设计测试用例。
第7章04 最终记忆主线
这一章可以用一句话概括:
白盒测试是基于代码结构和程序逻辑的测试,分为静态白盒测试和动态白盒测试;静态白盒测试通过评审、阅读、走查、检查和审计发现缺陷;动态白盒测试通过控制流覆盖、基本路径、循环测试和数据流测试生成测试用例并评估测试充分性。
最需要优先掌握的是:
- 白盒测试 = 结构化测试;
- 白盒测试基于代码,黑盒测试基于规约;
- 静态白盒测试定义、优点和方法;
- 动态白盒测试流程与覆盖标准意义;
- 六种控制流覆盖准则定义和区别;
- 语句覆盖、判定覆盖、条件覆盖、判定条件覆盖、条件组合覆盖、路径覆盖的易错关系;
- 基本路径、独立路径、圈复杂度三种计算方法;
- 简单循环、嵌套循环、串接循环、非结构循环的测试方法;
- 数据流测试中的 DEF、USE、P-use、C-use、DU-path、DC-path;
- Rapps 和 Weyuker 的 All-Defs、All-Uses、All-DU-Paths 等覆盖标准。