软件测试与质量保证课程笔记
Software Testing and Quality Assurance(SQA)
Session 1 Introduction
Why we need software testing?
- 我们需要软件
- 我们需要高质量的软件
- 我们需要一些方法来确保软件质量
Fundamentals of Software Quality Assurance
- 质量的定义是一个软件的完美程度
- 质量也可以被解释成满足顾客以下的需求:
- Explicit 明确的
- External 外在:features 特性,usability 可用性
- Implicit 暗含的
- Internal 内在:maintainability 可维护性,user experience 用户体验
- Explicit 明确的
Introducing Software Quality Assurance
- 需要在软件开发周期(SDLC)的**每一个阶段(Each phase)**进行软件质量的保证
- SQA是监控(monitor)和改善(improve)软件开发过程的一个有计划的(planned)、**系统(systematic)**的方法。
Quality Assurance and Quality Control
-
Quality activities 可以被分为两类:
- Preventive activities 预防性活动
- Detective activities 检测性活动
-
QA面向的是缺陷的预防,它被用来在发展和不断提升的过程中去实现一个组织定义好的质量政策
- Quality Audit 质量审核
- Process definition 过程定义
- Tool selection 工具选择
- Training 培训
- Peer review 同行评审
- Requirements tracking 需求跟踪
- Quality metrics collection 质量量度收集
-
QC是将产品的质量去和特定的标准对比的过程,当质量未达到应用标准时会采取一定的措施
- QC面向的是缺陷的检测
- Inspection 检查
- Testing 测试
- Checkpoint review 检验点审查
Testing Overview
-
What is testing?
- 分析**软件项目(software item)来检测(detect)已有的和所需要的情况之间的区别,同时去评价(evaluate)**软件项目的特性。
-
Who does testing?
-
Software Tester
-
Software Developer
-
Project Lead/Manager
-
End User
-
Crowdsourcing Testing
- Anyone-crowd worker
-
-
When to start testing?
-
越早越好
-
取决于开发模型
- 瀑布模型 vs 增量模型
-
测试在SDLC的不同阶段形式也不同
-
-
When to stop testing?
-
永远不会结束
-
一些方面
-
测试的deadlines
-
管理层决定
-
测试样例执行完成
-
功能或代码覆盖到达某一点
-
bug率低于某一个特定的值并且没有一些严重的bug被识别出来
-
-
Session 2 Preliminary to software testing
What is defect?
- Error(错误):在写程序过程中发生
- Fault(故障):是一个或多个错误的表现(internal state 内在状态)
- Failure(失效):当一段错误的代码被执行引起了一个错误的状态并且被传播到程序的输出中
- Incident(事故):当Failure发生时没有任何信息被显示
Software defect definition
-
各种的软件问题
-
存在于代码,数据和文档中
-
与用户的期望不同
-
例如:
- 软件的功能不能被正确执行
- 缺点
- 运行缓慢
- 不一致性
- Ctrl + S 不能保存设置
- 用于界面设计缺陷
- 一个按钮本来应该显示五个字母,但是只有三个字母可以被看见
BUG kinds
-
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 内部测试
- 测试的关键:
- 源代码 / 设计
- 黑盒测试
- 测试组件是否符合软件需求规格说明书 SRS
- behavioral testing 行为测试
- external testing 外在测试
- input-output testing 输入输出的测试
- 测试的关键:
- Specification 软件需求规格说明书
Testing Life Cycle
Model of testing
-
The V model
- 用于减少纠正错误的代价,缺陷必须在开发生命周期的早期就被发现
- V模型提出了一种软件开发的方法,使得软件开发和软件测试同时开始
-
V模型的缺陷
- 只关注了动态的测试(dynamic testing)
- 没有提及静态测试技术的优点和有效性
-
The W model
- 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
Session 3 White-Box Testing
Basic concepts
- 白盒测试
- 是一种Validation的技术,用来检查代码是否像预期一样工作
- 代码的逻辑和结构是可见的
White-box Testing | Black-box Testing | |
---|---|---|
程序结构 | 已知程序结构 | 未知程序结构 |
规模 | 小规模测试 | 大规模测试 |
依据 | 详细设计说明,源代码 | 需求说明,概要设计说明 |
面向 | 程序结构 | 输入输出接口,功能要求 |
适用 | 单元测试 | 集成,系统,验收测试 |
测试人员 | 开发人员 | 专门测试人员,用户 |
优点 | 能够对程序内部的特定部位进行覆盖 | 能站在用户立场上进行测试 |
缺点 | 无法检验程序的外部特性,不能检测对需求的遗漏 | 不能测试程序内部特定部位,如果程序规格说明有误,则无法发现 |
-
白盒测试的难点
- 对于多个选择和流程的循环网来说,不同路径的所有可能路径的总数是天文数字
- 循环20次,有5^20次路径
-
不适用穷举调式(exhaustive testing)的原因
- 过于耗费时间
- 如果有路径遗漏(path omission),穷举调试无法检测到错误
- 不能发现与数据有关的错误(例如界限和特定的输入)
-
白盒测试基于以下原则
- 模块中所有**独立(independent)**的路径必须被实现过至少一次。 Basis Path Testing
- 所有的逻辑值需要有两个测试案例:true和false。 Logic Coverage
- 检查
- 程序内部数据结构,并确保其结构的有效性。Static Testing + Data Flow Testing
- 在可操作的范围内,运行所有循环。 Loop Testing
Logic Coverage
- 逻辑覆盖的分类 Logic Coverage
- Statement Coverage
- Decision Coverage
- Condition Coverage
- Condition-Decision Coverage
- Condition Combination Coverage
- Path Coverage
- Complete Coverage
- Modified Condition/Decision Coverage
Statement Coverage 语句覆盖
- 确保每个可执行语句至少被运行一次
- 在图中,所有可执行的语句都在L1中,所以选择L1来设计测试案例
- $L1 = [(A=2)and(B=0)]or[(A>1)and(B=0)and(x/A>1)]$
- 假设有三个变异体(Mutant)
- 第一个判断变成 (A > 1) or (B=0)
- 第二个判断变成 (A = 2) and (X>0)
- 测试用例A=2,B=0,X=3无法检测出错误
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,这两组测试用例无法检测出错误
-
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 |
- 满足CCC,但是只覆盖了三个路径,遗漏了acd
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 |
- 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 |
-
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至少包含了一个条件
-
程序流程图和控制流图的转换
练习题
-
语句覆盖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 |
- 条件判定覆盖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
- 确定基本路径的数量
- 设计测试用例来执行每条路径
环路复杂度计算
- Cyclomatic complexity
- 每当新增一条独立路径,要能覆盖多一个结点或多一条边
- $Edges - Nodes + 2$
- $Predicate Nodes+1$
- 判定结点,要做出逻辑选择的结点(出度≥2)
- 循环入口出口结点
- 判断分支结点
- $closed regions+1$
练习
-
输入: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
- 非结构化循环
简单循环 Simple Loops
- 若n为循环的最大可能次数
- 执行0次
- 执行1次
- 执行2次
- 执行m次,m<n
- 执行n-1次,n次,n+1次
嵌套循环 Nested Loops
-
从最内层循环开始
-
对最内存循环进行Simple Loops测试
-
一层一层向外,所有外层取最小值,其余的嵌套循环取典型值typical values
串联循环 Concatenated Loops
- 如果每个循环独立于其他循环
- 使用简单循环的测试方法
- 反之
- 需要应用循环测试
非结构化循环
- 重新设计循环
- 不要使用
go to
语句
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] |
Data Flow Testing
- 变量的定义,使用和删除的位置
- 检测的错误
- 错误的声明或输入语句
- 缺失定义语句
- 谓词错误
Variable Definitions and Uses
-
定义变量
- 赋值表达式的左侧
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 — 变量不存在,被销毁了
-
9种配对方式
- dd — 定义了之后又定义了
- 未被使用过,但定义了两次,有可能是错的
- du — 定义了之后使用了
- dk — 定义了然后被销毁了
- 有可能是错的
- ud
- uu
- uk
- kd
- ku - 销毁之后又被使用
- 严重错误
- kk - 销毁之后又被销毁
- 有可能是错的
- dd — 定义了之后又定义了
Data flow graph
- 所有变量
- definition
- use
- destruction
- 流程
- 画图
- 静态测试
- 动态测试
- 针对变量x
- ~define
- define-define
- define-use
- 针对变量y
- ~use
- use-define
- define-use
- use-kill
- define-kill
- 针对变量z
- ~kill
- kill-use
- use-use
- use-use
- use-define
- kill-kill
- kill-define
- define-use
Session 6 Data Flow Testing
- 定义清除 definition clear(def-clear)
- 对变量没有重复定义(re-definition)
- 定义使用对 definition-use pair(du-pair)
- 对变量来说,从定义到使用的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
-
-
DU-PATH
- 对于任意的变量,如果变量v被定义,必须满足
- 如果是v的c-use在nk结点上,则必须保证**<n1,n2,…,nj,nk>是一条def-clear且simple**的path
- simple: 没有重复边
- 如果是v的p-use在**<nj,nk>边上,那么<n1,n2,…nj>必须是def-clear且loop-free**的path
- loop-free: 没有重复结点
- 如果是v的c-use在nk结点上,则必须保证**<n1,n2,…,nj,nk>是一条def-clear且simple**的path
- 对于任意的变量,如果变量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,它所有定义的地方都至少覆盖一次
-
全使用覆盖 All-Uses
- 关于某个变量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
Session 7 Black-Box Testing — Boundary Value Analysis
Introduction of Black-Box Testing
- 黑盒测试设计技术
- Boundary Value Analysis 边界值分析
- Equivalence Patitioning
- Decision Table 判定表
- Cause-Effect Graph 因果图
- Combinatiorial Test 组合测试
Boundary Value Analysis
- 基本思想
- 错误往往聚集在边界上
- 对所有输入的变量取
- min
- min+,略微比下界大
- nom(nominal, typical)
- max-,略微比上界小
- max+
- 例如:数组,循环,≤
- 输入的值必须在0-100中间
- 测试用例
- 0, 1, 56, 99, 100
- Robustness Testing 健壮性测试
- 是对边界值分析的简单扩展
- max+和min-的测试用例
- 基于单缺陷假设 Single fault assumption
- Normal Boundary Values 基本边界值分析
- Robustness Boundary Values 健壮性边界值分析
- 考虑多个变量取极端值
- Multiple Variable of Boundary Values (Worst-Case Testing) 多变量的边界值分析
- Robust Multiple Variable of Boundary Values (Robust Worst-Case Testing) 多变量的健壮性边界值分析
Example
-
函数F,变量x和y
- a <= x <= b
- c <= y <= d
-
Normal Boundary Values
- 针对n个变量,4n+1个测试用例
-
Robustness Boundary Values
-
针对n个变量,6n+1个测试用例
-
浅蓝色的点不能取
-
Multiple Variable of Boundary Values
- 针对n个变量,5^n个测试用例
-
Robust Multiple Variable of Boundary Values
- 针对n个变量,7^n个测试用例
Examples
The Triangle Problem
-
输入三个整数a, b, c作为三条边的长度
- 1<=a<=200
- 1<=b<=200
- 1<=c<=200
-
基本边界值分析需要4n+1= 13个测试用例
a b c Equilateral Isosceles scalene NotATriangle 1 100 100 True True 2 100 100 True True 199 100 100 True True 200 100 100 True 100 1 100 True True 100 2 100 True True 100 199 100 True True 100 200 100 True 100 100 1 True True 100 100 2 True True 100 100 199 True True 100 100 200 True True True 100 100 100 True True
The NextDate Problem
- 输入三个整型变量 month, day, year
- 1 <= month <= 12
- 1 <= day <= 31
- 1812 <= year <= 2012
- 输出这个日期的第二天
- 测试用例
- month: 0, 1, 2, 6, 11, 12, 13
- day: 0, 1, 2, 15, 30, 31, 32
- year: 1811, 1812, 1813, 1900, 2011, 2012, 2013
Limitation of BVA
- 适用于物理数量型的变量
- 对于逻辑类变量来说,例如PIN或者电话号码
Advantages of BVA
limitations of BVA
Exercise 1
There are three integer inputs x, y, z, corresponding to the length, width and height of a rectangle respectively. All of these three inputs are in the range of [2, 20], the output is the volume of the rectangle.
-
List the number of test cases that needed by four types of boundary value analysis respectively
- normal : 4n+1 = 13
- robustness: 6n+1 = 19
- mutiple: 5^n = 125
- robustness mutiple: 7^n = 49*7 = 343
-
Design the test cases by Robustness Boundary Value Analysis.
x y z volume 1 11 11 121 2 11 11 242 3 11 11 363 19 11 11 19*121 20 11 11 20*121 21 11 11 21*121 11 1 11 11 2 11 11 3 11 11 19 11 11 20 11 11 21 11 11 11 1 11 11 2 11 11 3 11 11 19 11 11 20 11 11 21 11 11 11
Equivalence Partitioning
- 等价类划分
- Partition
Equivalence Class 等价类
- 利用等价类中的一种测试用例来代表整个等价类
- 来检测是否有缺陷
Equivalence Class Testing 等价类测试
- 弱一般等价类测试
- Weak Normal Equivalence Class Testing
- 强一般等价类测试
- Strong Normal Equivalence Class Testing
- 弱健壮等价类测试
- Weak Robust Equivalence Class Testing
- 强健壮等价类测试
- Strong Robust Equivalence Class Testing
- Strong ECTesting
- 所有变量的迪卡尔积
- ECx × ECy = {(x1,y1),(x1,y2),(x2,y1),(x2,y2),(x3,y1),(x3,y2)}
- Weak ECTesting
- 每一个等价类都被覆盖到过
- 例如{(x1,y1),(x2,y2),(x3,y2)}
- 这里x1, x2, x3被覆盖
- y1, y2被覆盖
Interaction Fault
- Simple Fault 一个变量
- Pair-wise interaction fault 两个变量
int x, y; input(x, y); if(x>=0){ // 这里应该是 x+1>=0 output(2*y); }else{ output(3*y); }
$x,y\in{-2,-1,1,2}$
则弱测试就足够检测出程序中的问题
int x, y; input(x, y); if(x&&y){ // 这里应该是 x||y output(f(x,y)); }else{ output(g(x,y)); }
$x,y\in{T,F}$
需要强测试才能检测出fault
-
强测试的缺陷
- 会产生很多不可能的,赘余的,没有用的测试用例
-
弱健壮等价类测试
- 对于有效的输入,等同于弱一般等价类测试
- 对于无效的输入,必须只有一个无效的值,其余的值还是有效的
-
强健壮等价类测试
-
考虑所有无效输入的值
-
-
混合路径 Hybrid approach
-
强一般+弱健壮
-
-
测试用例数量的计算
-
有n个变量$x_1,x_2,x_3…,x_n$
-
有效的等价类${E(x_1),E(x_2),E(x_3)…,E(x_n)}$
-
无效的等价类${I(x_1),I(x_2),I(x_3)…,I(x_n)}$
- 弱一般
- $max{E(x_1),E(x_2),E(x_3)…,E(x_n)}$
- 强一般
- $E(x_1)E(x_2)…*E(x_n)$
- 弱健壮
- $max{E(x_1),E(x_2),E(x_3)…,E(x_n)}+\sum_{i=1}^{n}I(x_i)$
- 强健壮
- $\prod^n_{i=1}(E(X_i)+I(x_i))$
- 混合
- $E(x_1)E(x_2)…*E(x_n)+\prod^n_{i=1}I(x_i)$
- 弱一般
Example
针对三角形划分等价类
- Valid ECs:
- V1 = {<a,b,c> : the triangle with sides a,b,and c is equilateral}
- V2 = {<a,b,c> : the triangle with sides a,b,and c is isosceles}
- V3 = {<a,b,c> : the triangle with sides a,b,and c is scalene}
- Invalid ECs:
- IV1 = {<a,b,c> : sides a,b,and c do not form a triangle}
- IV2 = {<a,b,c>: a is not in the range of permitted values}
- IV3 = {<a,b,c>: b is not in the range of permitted values}
- IV4 = {<a,b,c>: c is not in the range of permitted values}
-
- 针对2,没有测试不同的等腰
- 针对4,没有测试上边界
- 针对5,6,7,没有测试超上边界的值