Software Testing and Quality Assurance(SQA)
Session 1 Introduction
Why we need software testing?
- 我们需要软件
- 我们需要高质量的软件
-
Fundamentals of Software Quality Assurance
质量的定义是一个软件的完美程度
质量也可以被解释成满足顾客以下的需求:
需要在软件开发周期(SDLC)的每一个阶段(Each phase)进行软件质量的保证
SQA是监控(monitor)和改善(improve)软件开发过程的一个有计划的(planned)、系统(systematic)的方法。
Quality Assurance and Quality Control
Quality activities 可以被分为两类:
- Preventive activities 预防性活动
- Detective activities 检测性活动
- Preventive activities 预防性活动
- QA面向的是缺陷的预防,它被用来在发展和不断提升的过程中去实现一个组织定义好的质量政策
- Quality Audit 质量审核
- Process definition 过程定义
- Tool selection 工具选择
- Training 培训
- Peer review 同行评审
- Requirements tracking 需求跟踪
- Quality metrics collection 质量量度收集
- Quality Audit 质量审核
QC是将产品的质量去和特定的标准对比的过程,当质量未达到应用标准时会采取一定的措施
What is testing?
- 分析软件项目(software item)来检测(detect)已有的和所需要的情况之间的区别,同时去评价(evaluate)软件项目的特性。
- 分析软件项目(software item)来检测(detect)已有的和所需要的情况之间的区别,同时去评价(evaluate)软件项目的特性。
- Who does testing?
- Software Tester
- Software Developer
- Project Lead/Manager
- End User
- Crowdsourcing Testing
- Anyone-crowd worker
- Anyone-crowd worker
- Software Tester
- When to start testing?
- 越早越好
- 取决于开发模型
- 瀑布模型 vs 增量模型
- 瀑布模型 vs 增量模型
- 测试在SDLC的不同阶段形式也不同
- 越早越好
When to stop testing?
Error(错误):在写程序过程中发生
- Fault(故障):是一个或多个错误的表现(internal state 内在状态)
- Failure(失效):当一段错误的代码被执行引起了一个错误的状态并且被传播到程序的输出中
Incident(事故):当Failure发生时没有任何信息被显示
Software defect definition
各种的软件问题,存在于代码,数据和文档中
- 与用户的期望不同
例如:
Syntactic errors 语法错误
- Mal-formed program 畸形的程序
int square(int x){
return x*x
}
- Semantic erros 语义错误
- Symbol errors
int square(int x){
return n*n;
}
- Type errors
int squre(float x){
return x*x;
}
- Logical errors 逻辑错误
- 编译器:“no errors”
int square(int x){
return x+x;
}
Verification vs. Validation
- Verification(验证):软件应该符合它的软件需求规格说明书(静态)
- Validation(确认):这个软件做的是用户真的需要的(动态)
方面 | Verification | Validation |
---|---|---|
含义 | 你做的方法对吗 | 你做的是对的东西吗 |
目标 | 确保软件系统满足了所有的功能要求 | 确保功能符合预期的行为 |
时间 | Verification先进行,包括检查文档和代码等 | Validation后进行,包括整体产品的检查 |
参与者 | 开发者完成 | 测试人员完成 |
活动 | 需要的是静态的活动,包括复审,程序规格覆核和一些确认软件是否正确的检查 | 需要动态的活动包括针对需求去执行软件 |
Testing vs. debugging
- Testing
包含的是对于软件中的bug的识别,而不需要纠正。
Testing是在测试阶段实行的。 Debugging
包含的是识别(identifying),分离(isolating)并且修正(fixing)问题和bug。
Debugging是在开发阶段实行的,同时要进行单元测试(Unit Testing)或者在修复已报告的bug的阶段
White-box vs. Black-box Test
白盒测试
- 测试组件是否符合开发设计要求
- structural testing 结构化测试
- internal testing 内部测试
- 测试的关键:
- 源代码 / 设计
- 源代码 / 设计
- 测试组件是否符合开发设计要求
黑盒测试
The V model
- 用于减少纠正错误的代价,缺陷必须在开发生命周期的早期就被发现
- V模型提出了一种软件开发的方法,使得软件开发和软件测试同时开始
- 用于减少纠正错误的代价,缺陷必须在开发生命周期的早期就被发现
- V模型的缺陷
- 只关注了动态的测试(dynamic testing)
- 没有提及静态测试技术的优点和有效性
- 只关注了动态的测试(dynamic testing)
- The W model
- W模型是针对V模型限制的一种扩展和补充
- 只关注了各开发阶段的静态测试
- 这些技术比动态测试更加便宜更加高效
- W模型是针对V模型限制的一种扩展和补充
- 从Test the Reuirements到Test the Design Document都是Verification
- Unit Test到Acceptance Test都是Validation
Types of testing
测试用例生成的起源 Source of test generation | Artifact | Techique | | —- | —- | | 需求 | 黑盒 | | 代码 | 白盒 | | 需求和代码 | 黑盒和白盒 | | 正式模型:图或者数学的表达方式 | 基于模型的表达 | | 组件的接口 (Component’s interface) | 接口测试 |
生命周期阶段 Life cycle phase | Phase | Techique | | —- | —- | | 编程 | 单元测试 | | 集成 | 集成测试 | | 系统集成 | 系统测试 | | 发布系统(先行版) | Alpha/Beta-tesing/Acceptance tesing | | 维护 | 回归测试 |
测试目的为导向的测试 Goal-directed testing | Goal | Techique | | —- | —- | | 安全性 | 安全性测试 | | 无效输入 | 健壮性测试 | | GUI 界面错误 | GUI 测试 | | 系统性能 | 性能测试 | | 客户接受度 | 验收测试 |
Session 3 White-Box Testing
Basic concepts
白盒测试
- 是一种Validation的技术,用来检查代码是否像预期一样工作
- 代码的逻辑和结构是可见的
| | White-box Testing | Black-box Testing | | —- | —- | —- | | 程序结构 | 已知程序结构 | 未知程序结构 | | 规模 | 小规模测试 | 大规模测试 | | 依据 | 详细设计说明,源代码 | 需求说明,概要设计说明 | | 面向 | 程序结构 | 输入输出接口,功能要求 | | 适用 | 单元测试 | 集成,系统,验收测试 | | 测试人员 | 开发人员 | 专门测试人员,用户 | | 优点 | 能够对程序内部的特定部位进行覆盖 | 能站在用户立场上进行测试 | | 缺点 | 无法检验程序的外部特性,不能检测对需求的遗漏 | 不能测试程序内部特定部位,如果程序规格说明有误,则无法发现 |
- 是一种Validation的技术,用来检查代码是否像预期一样工作
白盒测试的难点
- 对于多个选择和流程的循环网来说,不同路径的所有可能路径的总数是天文数字
- 循环20次,有5^20次路径
- 对于多个选择和流程的循环网来说,不同路径的所有可能路径的总数是天文数字
- 不适用穷举调式(exhaustive testing)的原因
- 过于耗费时间
- 如果有路径遗漏(path omission),穷举调试无法检测到错误
- 不能发现与数据有关的错误(例如界限和特定的输入)
- 过于耗费时间
白盒测试基于以下原则
逻辑覆盖的分类 Logic Coverage
- Statement Coverage
- Decision Coverage
- Condition Coverage
- Condition-Decision Coverage
- Condition Combination Coverage
- Path Coverage
- Complete Coverage
- Modified Condition/Decision Coverage
- Statement Coverage
Statement Coverage 语句覆盖
- 确保每个可执行语句至少被运行一次
- 在图中,所有可执行的语句都在L1中,所以选择L1来设计测试案例
- 假设有三个变异体(Mutant)
- 第一个判断变成 (A > 1) or (B=0)
- 第二个判断变成 (A = 2) and (X>0)
- 第一个判断变成 (A > 1) or (B=0)
-
Decision Coverage 判定覆盖
确保每条判断语句的真假分支都至少走过一次
- 针对“Switch–Case”的语句就是多分支
- 测试案例(A, B, x)
- t1 = (2, 0, 3)经过ace,t2 = (1, 1, 1)经过abd
- t3 = (2, 1, 1)经过abe,t4 = (3, 0, 3)经过acd
- 但是如果把x>1错写成x<1,这两组测试用例无法检测出错误
- t1 = (2, 0, 3)经过ace,t2 = (1, 1, 1)经过abd
Decisions Coverage无法保证能检测出判断语句中的错误情况
Condition Coverage 条件覆盖
确保程序中每种情况可能的值至少都要实现一次
- A > 1 对应T1
- B = 0 对应T2
- A = 2 对应T3
X > 1 对应T4
| 测试用例 | 路径 | 条件真值Condition value | 覆盖路径Coverage branch | | —- | —- | —- | —- | | (2, 0, 4) | ace | T1 T2 T3 T4 | ce (T, T) | | (1, 1, 1) | abd | !T1 !T2 !T3 !T4 | bd (F, F) |下组测试用例证明,满足条件覆盖CC不一定满足判定覆盖DC
| 测试用例 | 路径 | 条件真值Condition value | 覆盖路径Coverage branch | | —- | —- | —- | —- | | (1, 0, 3) | abe | !T1 T2 !T3 T4 | be (F, T) | | (2, 1, 1) | abe | T1 !T2 T3 !T4 | be (F, T) |下组测试用例证明,满足判定覆盖DC不一定满足条件覆盖CC
| 测试用例 | 路径 | 条件真值Condition value | 覆盖路径Coverage branch | | —- | —- | —- | —- | | (2, 0, 4) | ace | T1 T2 T3 T4 | ce (T, T) | | (3, 1, 1) | abd | T1 !T2 !T3 !T4 | bd (F, F) |
Condition/Decision Coverage 条件判断覆盖
- 确保每条判断语句的真假分支都至少走过一次
- 同时确保程序中每种情况可能的值至少都要实现一次
-
Condition Combination Coverage 条件组合覆盖
每个判定所有可能的条件组合
- 包括了DC,CC,CDC
- A > 1,B = 0 T1T2
- A > 1,B ≠ 0 T1!T2
- A ≯ 1,B = 0 !T1T2
- A ≯ 1,B ≠ 0 !T1!T2
- A = 2,X > 1 T3T4
- A = 2,X ≯ 1 T3!T4
- A ≠ 2,X>1 !T3T4
- A ≠ 2,X ≯ 1 !T3!T4
| 测试用例 | 路径 | Coverage condition | Combination Coverage No. | | —- | —- | —- | —- | | (2, 0, 4) | ace | T1 T2 T3 T4 | 1, 5 | | (2, 1, 1) | abe | T1 !T2 T3 !T4 | 2, 6 | | (1, 1, 1) | abe | !T1 T2 !T3 T4 | 3, 7 | | (1, 1, 1) | abd | !T1 !T2 !T3 !T4 | 4, 8 |
-
Path Coverage 路径覆盖
-
Complete Coverage 全覆盖
Complete Coverage = Condition Combination Coverage + Path Coverage
| 测试用例 | 路径 | Coverage condition | Combination Coverage No. | | —- | —- | —- | —- | | (2, 0, 4) | ace | T1 T2 T3 T4 | 1, 5 | | (2, 1, 1) | abe | T1 !T2 T3 !T4 | 2, 6 | | (1, 0, 3) | abe | !T1 T2 !T3 T4 | 3, 7 | | (1, 1, 1) | abd | !T1 !T2 !T3 !T4 | 4, 8 | | (3, 0, 3) | acd | T1 T2 !T3 !T4 | 1, 8 |
Modified Condition/Decision Coverage
- 每个入口和出口都被调用
- 满足判定覆盖
- 满足条件覆盖
- 在每个条件的判定中都必须显示出它能独立地影响判定的结果
| 测试用例 | 路径 | Coverage condition | Combination Coverage No. | | —- | —- | —- | —- | | (2, 0, 4) | ace | T1 T2 T3 T4 | 1, 5 | | (2, 1, 1) | abe | T1 !T2 T3 !T4 | 2, 6 | | (1, 0, 3) | abe | !T1 T2 !T3 T4 | 3, 7 | | (1, 1, 1) | abd | !T1 !T2 !T3 !T4 | 4, 8 |
练习题
Statement Coverage
| 测试用例 | 覆盖情况 | | —- | —- | | (18, 18) | S3 | | (-1, -1) | S1 | | (1, 1) | S2 |Decision Coverage
| 测试用例 | 覆盖情况 | | —- | —- | | (18, 18) | YY | | (10, 10) | YN | | (-1, -1) | NN | | (1, 1) | NY |Condition Coverage
- T1: X>8
- T2: Y>5
- T3: X>0
- T4: Y>0
- T5: X>16
- T6: Y>10
| 测试用例 | 覆盖情况 | | —- | —- | | (18, 18) | T1, T2, T5, T6 | | (10, 10) | T1, T2, !T5, !T6 | | (-1, -1) | !T1, !T2, !T3, !T4 | | (1, 1) | !T1, !T2, T3, T4 |
- T1: X>8
Condition/Decision Coverage
| 测试用例 | 判定覆盖情况 | 条件覆盖情况 | | —- | —- | —- | | (18, 18) | YY | T1, T2, T5, T6 | | (10, 10) | YN | T1, T2, !T5, !T6 | | (-1, -1) | NN | !T1, !T2, !T3, !T4 | | (1, 1) | NY | !T1, !T2, T3, T4 |MCDC
| 测试用例 | 条件覆盖情况 | | | —- | —- | —- | | (18, 18) | T1, T2, T5, T6 | T T | | (15,11) | T1, T2, !T5, T6 | T F | | (17, 10) | T1, T2, T5, !T6 | T F | | (10, 10)舍 | T1, T2, !T5, !T6 | T F | | (-1, -1) | !T1, !T2, !T3, !T4 | F F | | (-1, 6) | !T1, T2, !T3, T4 | F T | | (10, -1) | T1, !T2, T3, !T4 | F T | | (1, 1)舍 | !T1, !T2, T3, T4 | F T |Condition Combination Coverage
- X>8, Y>5 T1 T2
- X>8, Y<=5 T1 !T2
- X<=8, Y>5 !T1 T2
- X<=8, Y<=5 !T1 !T2
- X>0, Y>0 T3 T4
- X>0, Y<=0 T3 !T4
- X<=0, Y>0 !T3 T4
- X<=0, Y<=0 !T3 !T4
- X>16, Y>10 T5 T6
- X>16, Y<=10 T5 !T6
- X<=16, Y>10 !T5 T6
- X<=16, Y<=10 !T5!T6
| 测试用例 | 组合覆盖情况 | 条件覆盖情况 | | —- | —- | —- | | (18, 18) | 1,9 | T1, T2, T5, T6 | | (15,11) | 1,10 | T1, T2, !T5, T6 | | (17, 10) | 1,11 | T1, T2, T5, !T6 | | (10, 10) | 1,12 | T1, T2, !T5, !T6 | | (-1, -1) | 4,8 | !T1, !T2, !T3, !T4 | | (-1, 6) | 3,7 | !T1, T2, !T3, T4 | | (10, -1) | 2,6 | T1, !T2, T3, !T4 | | (1, 1) | 4, 5 | !T1, !T2, T3, T4 |
Path Coverage
| 测试用例 | 路径 | | —- | —- | | (18, 18) | d | | (10, 10) | c | | (-1, -1) | a | | (1, 1) | b |Complete Coverage
| 测试用例 | 组合覆盖情况 | 条件覆盖情况 | | —- | —- | —- | | (18, 18) | 1,9 | T1, T2, T5, T6 | | (15,11) | 1,10 | T1, T2, !T5, T6 | | (17, 10) | 1,11 | T1, T2, T5, !T6 | | (10, 10) | 1,12 | T1, T2, !T5, !T6 | | (-1, -1) | 4,8 | !T1, !T2, !T3, !T4 | | (-1, 6) | 3,7 | !T1, T2, !T3, T4 | | (10, -1) | 2,6 | T1, !T2, T3, !T4 | | (1, 1) | 4,5 | !T1, !T2, T3, T4 |
A AND (B OR C)
- DC
| A, B, C | Decsion | Condition | | —- | —- | —- | | 1, 1, 1 | T | A B C | | 1, 1, 0 | T | A B !C | | 1, 0, 1 | T | A !B C | | 0, 1, 1 | F | !A B C | | 1, 0, 0 | F | A !B !C | | 0, 1, 0 | F | !A B !C | | 0, 0, 1 | F | !A !B C | | 0, 0, 0 | F | !A !B !C |
Control Flow Graph
- 可以认为是一种简化的程序流程图,重点去凸显控制流的结构
- 结构
- 箭头arrow用边edge表示控制流走向
- 结点node都用圆圈circle来表示若干行为
- 由边和结点圈起来的地方叫做regions
- predicate node至少包含了一个条件
- 箭头arrow用边edge表示控制流走向
- 程序流程图和控制流图的转换
练习题
语句覆盖SC
| 测试用例(A, B, S) | 语句覆盖情况 | | —- | —- | | 2, 2, 0 | e,c | | 0, 0, 10000 | b,f |判定覆盖DC
| 测试用例(A, B, S) | 判定覆盖情况 | | —- | —- | | 2, 2, 0 | T, F | | 0, 0, 10000 | F, T |条件覆盖CC
- A>1 对应T1
- B>1 对应T2
- S>9999 对应T3
| 测试用例(A, B, S) | 条件覆盖情况 | | —- | —- | | 2, 2, 0 | T1, T2, !T3 | | 0, 0, 10000 | !T1, !T2, T3 |
- A>1 对应T1
条件判定覆盖CDC
| 测试用例(A, B, S) | 条件覆盖情况 | | —- | —- | | 2, 2, 0 | T1, T2, !T3 | | 0, 0, 10000 | !T1, !T2, T3 |条件组合覆盖CCC
| 测试用例(A, B, S) | 条件覆盖情况 | | —- | —- | | 2, 2, 10000 | T1, T2, T3 | | 1, 2, 10000 | !T1, T2, T3 | | 1, 1, 9997 | !T1, !T2, !T3 | | 2, 1, 9997 | T1, !T2, !T3 |
void test(int iStudents, int iData[ ])
{
int x=0;
int y=0;
int z=0;
for(int loop=0; loop< iStudents;loop++)
{
int dNum= iData[loop];
if(dNum<60)
x++;
else
{
if(dNum>=60)
y++;
else
z++;
}
}
}
- 环路复杂度 = 4
- 基本路径数 = 4
| 路径 | 输入->输出 | | —- | —- | | 3-4-17 | iStudents = 0 -> x=0, y=0, z=0 | | 3-4-7-8-16-4-17 | iStudents = 1, iData = [59] -> x=1, y=0, z=0 | | 3-4-7-11-12-15-16-4-17 | iStudents = 1, iData = [61] -> x=0, y=1, z=0 | | 3-4-7-11-14-15-16-4-17 | null |
Session 4 Basis Path Testing
- 使用这种方法生成一系列线性无关路径(基本路径)
- 使用基本路径的原因
- 穷举法难以实现
- 使用流程化的设计去获取一系列逻辑复杂度测量
- 测试用例至少执行了每条语句一次
- 穷举法难以实现
- 介于全路径覆盖和分支覆盖
如何设计
Cyclomatic complexity
输入:Score[i]
- 输出:n2, sum, average
不进行条件分解,要满足分支覆盖
- 环路复杂度 = 4
| 路径 | 输入(Scores数组) | | —- | —- | | 1-2-7-8-10 | [-1] | | 1-2-7-9-10 | null | | 1-2-3-4-5-6-7-8-10 | [-2,-1] | | 1-2-3-4-6-7-9-10 | [1, -1] |
进行条件分解
- 环路复杂度 = 6
| 路径 | 输入 | | —- | —- | | 1-2-3-4-5-6-7-8-2-9-10-12 | [1, -1] | | 1-2-3-4-5-6-8-2-9-10-12 | [101,-1] | | 1-2-3-4-5-8-2-9-10-12 | [-2, -1] | | 1-2-3-9-10-12 | null | | 1-2-9-10-12 | [-1] | | 1-2-9-11-12 | null |
Session 5 Loop Testing
- Simple Loops
- 简单循环
- 简单循环
- Nested Loops
- 嵌套循环
- 嵌套循环
- Concatenated Loops
- 串联循环
- 串联循环
Unstructured Loops
若n为循环的最大可能次数
从最内层循环开始
- 对最内存循环进行Simple Loops测试
一层一层向外,所有外层取最小值,其余的嵌套循环取典型值typical values
串联循环 Concatenated Loops
如果每个循环独立于其他循环
- 使用简单循环的测试方法
- 使用简单循环的测试方法
反之
重新设计循环
-
Z path coverage
测试循环的简单方法就是使用 Z path coverage
- 就是把循环简化为IF结构
-
例题
基本路径
- 3.1-3.2-12
- 3.1-3.2-5-6.1-10-3.3-3.2-12
- 3.1-3.2-5-6.1-6.2-10-3.3-3.2-12
- 3.1-3.2-5-6.1-6.2-8-6.1-6.2-10-3.3-3.2-12
| 路径 | 测试用例 numbers[], array_size | 输出 | | —- | —- | —- | | 3.1-3.2-12 | [1,2], 0 | [1,2] | | 3.1-3.2-5-6.1-9-3.3-3.2-12 | null | null | | 3.1-3.2-5-6.1-6.2-10-3.3-3.2-12 | [1,2], 2 | [1,2] | | 3.1-3.2-5-6.1-6.2-8-6.1-10-3.3-3.2-12 | [2,1], 2 | [1,2] |
- 3.1-3.2-12
Data Flow Testing
- 变量的定义,使用和删除的位置
检测的错误
定义变量
- 赋值表达式的左侧
y = 7
- 在输入语句中
input(y)
- 输出时的调用
DOIT(X:IN,Y:OUT)
- 赋值表达式的左侧
- 使用变量
- 赋值语句的右侧
y = x+17
- 作为函数参数被调用
y=sqrt(x)
- 分支语句中
if x>0 then
- p-use
- 分支中使用变量
- 分支中使用变量
- c-use
- 非分支中使用变量
- 非分支中使用变量
- 赋值语句的右侧
- 一些变量可能即被定义又被使用
y=y+x
y:in/out
- 变量第一次出现的三种可能存在
- ~d — 变量不存在,被定义了
- ~u — 变量不存在,被使用了
- ~k — 变量不存在,被销毁了
- ~d — 变量不存在,被定义了
9种配对方式
所有变量
- definition
- use
- destruction
- definition
- 流程
- 画图
- 静态测试
- 动态测试
- 画图
- 针对变量x
- ~define
- define-define
- define-use
- ~define
- 针对变量y
- ~use
- use-define
- define-use
- use-kill
- define-kill
- ~use
针对变量z
定义清除 definition clear(def-clear)
- 对变量没有重复定义(re-definition)
- 对变量没有重复定义(re-definition)
- 定义使用对 definition-use pair(du-pair)
- 对变量来说,从定义到使用的def-clear路径
- 对变量来说,从定义到使用的def-clear路径
input(A, B) # 使用AB
if B>1: # 使用B
A = A+7 # 定义,使用A
if A>10: # 使用A
B = A+B # 定义B,使用AB
output(A, B) # 定义AB
定义
- simple
- 路径中的所有边不同
- 路径中的所有边不同
- loop-free
- 没有环路(经过的结点不重复)
| path | simple | loop-free | | —- | —- | —- | | <1,3,4,2> | yes | yes | | <1,2,3,2> | yes | no | | <1,2,3,1,2> | not | no | | <1,2,3,2,4> | yes | no |
- 没有环路(经过的结点不重复)
- simple
DU-PATH
- 对于任意的变量,如果变量v被定义,必须满足
- 如果是v的c-use在nk结点上,则必须保证
是一条def-clear且simple的path - simple: 没有重复边
- simple: 没有重复边
- 如果是v的p-use在
边上,那么 必须是def-clear且loop-free的path - loop-free: 没有重复结点
- loop-free: 没有重复结点
- 如果是v的c-use在nk结点上,则必须保证
- 对于任意的变量,如果变量v被定义,必须满足
针对变量A
| du-pair | d-c path | | —- | —- | | (1,2) | <1,2> | | (1,4) | <1,3,4> | | (1,5) | <1,3,4,5> | | | <1,3,5> | | (1,<3,4>) | <1,3,4> | | (1,<3,5>) | <1,3,5> | | (2,4) | <2,3,4> | | (2,5) | <2,3,4,5> | | | <2,3,5> | | (2,<3,4>) | <2,3,4> | | (2,<3,5>) | <2,3,5> |针对变量B
| du-pair | d-c path | | —- | —- | | (1,<1,2>) | <1,2> | | (1,<1,3>) | <1,3> | | (1,4) | <1,3,4> | | | <1,2,3,4> | | (1,5) | <1,3,5> | | | <1,2,3,5> | | (4,5) | <4,5> |全定义覆盖 All-Defs
- 关于某个变量v,它所有定义的地方都至少覆盖一次
- 关于某个变量v,它所有定义的地方都至少覆盖一次
- 全使用覆盖 All-Uses
- 关于某个变量v,所有引用的地方都至少覆盖一次
- 关于某个变量v,所有引用的地方都至少覆盖一次
- 例题
input(X,Y) // 使用X
while(Y>0) do
if (X>0) then
Y = Y-X;
else
input(X);
end_if
end_while
output(X,Y)
- 数据流图
- X
| du-pairs | d-c path | | —- | —- | | (1,<3,4>) | <1,2,3,4> | | | <1,2,3,4,(6,2,3,4)*> | | (1,<3,5>) | <1,2,3,5> | | (1,4) | <1,2,3,4> | | | <1,2,3,4,(6,2,3,4)*> | | (1,7) | <1,2,7> | | | <1,2,3,4,6,2,7> | | | <1,2,3,4,6,(2,3,4,6)*,2,7> | | (5, 4) | <5,6,2,3,4> | | | <5,6,2,3,4,(6,2,3,4)*> | | (5,7) | <5,6,2,7> × | | | <5,6,2,3,4,6,2,7> | | | <5,6,2,3,4,6,(2,3,4,6)*,2,7> | | (5,<3,4>) | <5,6,2,3,4> | | | <5,6,2,3,4,(6,2,3,4)*> | | (5,<3,4>) | <5,6,2,3,5> | | | <5,6,2,3,4,6,2,3,5> | | | <5,6,2,3,4,6,(2,3,4,6)*,2,3,5> |
- Y
| du-pairs | d-c path | du path | | —- | —- | —- | | (1,<2,7>) | <1,2,7> | √ | | (1,<6,3>) | <1,2,3,5,6,3> | × | | | <1,2,(3,5,6)*,3> | × | | (1,<6,7>) | <1,2,3,5,6,7> | √ | | (1,<2,3>) | <1,2,3> | √ | | (1,4) | <1,2,3,4> | √ | | | <1,2,3,5,6,3,4> | × | | (1,7) | <1,2,7> | √ | | | <1,2,3,5,6,7> | √ | | | <1,2,(3,4,6)*,7> inf | × | | (4,4) | <4,6,3,4> | | | (4,7) | <4,6,7> | √ | | | <(4,6,2,3)*,4,6,2,7> | × | | (4,<6,3>) | <4,6,3> | √ | | (4,<6,7>) | <4,6,7> | √ |
练习题
Program Commission (INPUT, OUTPUT)
‘
Dim locks, stocks, barrels As Integer
Dim lockPrice, stockPrice, barrelPrice As Real
Dim totalLocks, totalStocks, totalBarrels As Integer
Dim lockSales, stockSales, barrelSales As Real
Dim sales, commission: REAL
‘
lockPrice = 45.0
stockPrice = 30.0
barrelPrice = 25.0
totalLocks = 0
totalStocks = 0
totalBarrels = 0
‘
Input (locks)
While NOT(locks = -1) ‘Input device uses
-1 to indicate end of data
Input (stocks, barrels)
totalLockstotalLocks = totalLocks + locks
totalStockstotalStocks = totalStocks + stocks
totalBarrelstotalBarrels = totalBarrels + barrels
Input (locks)
EndWhile
‘
Output (“Locks sold: “, totalLocks)
Output (“Stocks sold: “, totalStocks)
Output (“Barrels sold: “, totalBarrels)
‘
lockSales = lockPrice totalLocks
stockSales = stockPrice totalStocks
barrelSales = barrelPrice totalBarrels
sales = lockSales + stockSales + barrelSales
Output (“Total sales: “, sales)
‘
If (sales > 1800.0)
Then
commission = 0.10 1000.0
commissioncommission = commission + 0.15 800.0
commissioncommission = commission +
0.20 (sales-1800.0)
Else If (sales > 1000.0)
Then
commission = 0.10 1000.0
commissioncommission = commission
+ 0.15 (sales-1000.0)
Else commission = 0.10 * sales
EndIf
EndIf
Output (“Commission is $”, commission)
‘
End Commission
- 控制流图
LockPrice | du-pairs | def-clear paths | du-path | | —- | —- | —- | | (7,24) | <7-13,(14-19),(14-19)*,20-24> | × | | | <7-13,14,20-24> | √ | | | <7-13,14-19,20-24> | √ |
TotalStocks | du-pairs | def-clear paths | du-path | | —- | —- | —- | | (11,17) | <11-13,14,15-17> | √ | | (11,22) | <11-13,14,20,21-22> | √ | | (11,25) | <11-13,14,20,21-25> | √ | | (17,17) | <17-19,14,15-17> | × | | (17,22) | <17-19,14,20,21-22> | √ | | (17,25) | <17-19,14,20,21-25> | √ |
Barrels | du-pairs | def-clear paths | du-path | | —- | —- | —- | | (15,18) | <15,16,17,18> | √ |
LockSales | du-pairs | def-clear paths | du-path | | —- | —- | —- | | (24,27) | <24,25,26,27> | √ |
Sales | du-pairs | def-clear paths | du-path | | —- | —- | —- | | (27,<29,30>) | <27,28,29,30> | √ | | (27,33) | <27,28,29,30-33> | √ | | (27,<34,35>) | <27,28,29,34,35> | √ | | (27,37) | <27,28,29,34,35,36,37> | √ | | (27,38) | <27,28,29,34,38> | √ |
Commission | du-pairs | def-clear paths | du-path | | —- | —- | —- | | (31,32) | <31,32> | √ | | (32,33) | <32,33> | √ | | (33,41) | <33,40,41> | √ | | (36,37) | <36,37> | √ | | (37,41) | <37,39,40,41> | √ | | (38,41) | <38,39,40,41,42> | √ |
Test cases | du-paths | variations | | —- | —- | | <7-13,14,20-24> | lockPrice = 45.0, lock = -1 | | <7-13,14,15-19,20-24> | lockPrice = 45.0, lock = 1, -1 | | <11-13,14,15-17> | totalStocks = 0, lock = 1, stocks = 1 | | <11-13,14,20,21-22> | totalStocks = 0, lock = -1 | | <11-13,14,20,21-25> | totalStocks = 0, lock = -1 | | <17-19,14,20,21-22> | lock = 1, -1 stocks = 1 | | <17-19,14,20,21-25> | lock = 1, -1 stocks = 1 | | <15,16,17,18> | barrels = 1 | | <24,25,26,27> | lock = 1, -1, lockSales = 45.0 | | <27,28,29,30> | lockSales = 4500, stockSales = 3000, barrelSales = 2500 | | <27,28,29,30-33> | lockSales = 4500, stockSales = 3000, barrelSales = 2500 | | <27,28,29,34,35> | lockSales = 450, stockSales = 300, barrelSales = 500 | | <27,28,29,34,35,36,37> | lockSales = 450, stockSales = 300, barrelSales = 500 | | <27,28,29,34,38> | lockSales = 45, stockSales = 30, barrelSales = 50 | | <31,32> | commission = 100 | | <32,33> | commission = 100 | | <33,40,41> | commission = 100, sales = 2000 | | <36,37> | commission = 100, sales = 1500 | | <37,39,40,41> | commission = 100, sales = 1500 | | <38,39,40,41,42> | commission = 100, sales = 1500 |