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 用户体验

        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(确认):这个软件做的是用户真的需要的(动态

白盒测试 - 图1

方面 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

        白盒测试 - 图2
        白盒测试 - 图3

        Model of testing

  • The V model

    • 用于减少纠正错误的代价,缺陷必须在开发生命周期的早期就被发现
    • V模型提出了一种软件开发的方法,使得软件开发和软件测试同时开始
  • 白盒测试 - 图4
  • V模型的缺陷
    • 只关注了动态的测试(dynamic testing)
    • 没有提及静态测试技术的优点和有效性
  • The W model
    • W模型是针对V模型限制的一种扩展和补充
    • 只关注了各开发阶段的静态测试
    • 这些技术比动态测试更加便宜更加高效
  • 白盒测试 - 图5
  • 从Test the Reuirements到Test the Design Document都是Verification
  • Unit Test到Acceptance Test都是Validation

    Types of testing

  1. 测试用例生成的起源 Source of test generation | Artifact | Techique | | —- | —- | | 需求 | 黑盒 | | 代码 | 白盒 | | 需求和代码 | 黑盒和白盒 | | 正式模型:图或者数学的表达方式 | 基于模型的表达 | | 组件的接口 (Component’s interface) | 接口测试 |

  2. 生命周期阶段 Life cycle phase | Phase | Techique | | —- | —- | | 编程 | 单元测试 | | 集成 | 集成测试 | | 系统集成 | 系统测试 | | 发布系统(先行版) | Alpha/Beta-tesing/Acceptance tesing | | 维护 | 回归测试 |

  3. 测试目的为导向的测试 Goal-directed testing | Goal | Techique | | —- | —- | | 安全性 | 安全性测试 | | 无效输入 | 健壮性测试 | | GUI 界面错误 | GUI 测试 | | 系统性能 | 性能测试 | | 客户接受度 | 验收测试 |

Session 3 White-Box Testing

Basic concepts

  • 白盒测试

    • 是一种Validation的技术,用来检查代码是否像预期一样工作
    • 代码的逻辑和结构是可见的
      | | White-box Testing | Black-box Testing | | —- | —- | —- | | 程序结构 | 已知程序结构 | 未知程序结构 | | 规模 | 小规模测试 | 大规模测试 | | 依据 | 详细设计说明,源代码 | 需求说明,概要设计说明 | | 面向 | 程序结构 | 输入输出接口,功能要求 | | 适用 | 单元测试 | 集成,系统,验收测试 | | 测试人员 | 开发人员 | 专门测试人员,用户 | | 优点 | 能够对程序内部的特定部位进行覆盖 | 能站在用户立场上进行测试 | | 缺点 | 无法检验程序的外部特性,不能检测对需求的遗漏 | 不能测试程序内部特定部位,如果程序规格说明有误,则无法发现 |
  • 白盒测试的难点

    • 对于多个选择和流程的循环网来说,不同路径的所有可能路径的总数是天文数字
    • 循环20次,有5^20次路径
  • 白盒测试 - 图6
  • 不适用穷举调式(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

白盒测试 - 图7

Statement Coverage 语句覆盖

  • 确保每个可执行语句至少被运行一次
  • 在图中,所有可执行的语句都在L1中,所以选择L1来设计测试案例

  • 假设有三个变异体(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
  1. A > 1,B = 0 T1T2
  2. A > 1,B ≠ 0 T1!T2
  3. A ≯ 1,B = 0 !T1T2
  4. A ≯ 1,B ≠ 0 !T1!T2
  5. A = 2,X > 1 T3T4
  6. A = 2,X ≯ 1 T3!T4
  7. A ≠ 2,X>1 !T3T4
  8. 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 |

练习题

白盒测试 - 图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

  1. X>8, Y>5 T1 T2
  2. X>8, Y<=5 T1 !T2
  3. X<=8, Y>5 !T1 T2
  4. X<=8, Y<=5 !T1 !T2
  5. X>0, Y>0 T3 T4
  6. X>0, Y<=0 T3 !T4
  7. X<=0, Y>0 !T3 T4
  8. X<=0, Y<=0 !T3 !T4
  9. X>16, Y>10 T5 T6
  10. X>16, Y<=10 T5 !T6
  11. X<=16, Y>10 !T5 T6
  12. 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
    白盒测试 - 图9
    | 测试用例 | 路径 | | —- | —- | | (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 |

白盒测试 - 图10
白盒测试 - 图11

Control Flow Graph

  • 可以认为是一种简化的程序流程图,重点去凸显控制流的结构
  • 结构
    • 箭头arrow用边edge表示控制流走向
    • 结点node都用圆圈circle来表示若干行为
    • 由边和结点圈起来的地方叫做regions
    • predicate node至少包含了一个条件
  • 程序流程图和控制流图的转换
    白盒测试 - 图12

白盒测试 - 图13

练习题

  • 白盒测试 - 图14
  • 语句覆盖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++;
}
}
}
白盒测试 - 图15

  • 环路复杂度 = 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

    • 每当新增一条独立路径,要能覆盖多一个结点或多一条边

      • 判定结点,要做出逻辑选择的结点(出度≥2)
      • 循环入口出口结点
      • 判断分支结点

    • 练习

  • 输入:Score[i]

  • 输出:n2, sum, average
    白盒测试 - 图16
  • 不进行条件分解,要满足分支覆盖

    • 白盒测试 - 图17
    • 环路复杂度 = 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] |
  • 进行条件分解

    • 白盒测试 - 图18
    • 环路复杂度 = 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-1次,n次,n+1次

      嵌套循环 Nested Loops

  • 从最内层循环开始

  • 对最内存循环进行Simple Loops测试
  • 一层一层向外,所有外层取最小值,其余的嵌套循环取典型值typical values

    串联循环 Concatenated Loops

  • 如果每个循环独立于其他循环

    • 使用简单循环的测试方法
  • 反之

    • 需要应用循环测试

      非结构化循环

  • 重新设计循环

  • 不要使用go to语句

    Z path coverage

  • 测试循环的简单方法就是使用 Z path coverage

  • 就是把循环简化为IF结构
  • 循环执行一次或零次

    例题

    白盒测试 - 图19白盒测试 - 图20

  • 基本路径

    • 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 - 销毁之后又被销毁
      • 有可能是错的

        Data flow graph

  • 所有变量

    • definition
    • use
    • destruction
  • 流程
    • 画图
    • 静态测试
    • 动态测试

白盒测试 - 图21

  • 针对变量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被定义,必须满足
      1. 如果是v的c-usenk结点上,则必须保证是一条def-clear且simple的path
        • simple: 没有重复边
      2. 如果是v的p-use边上,那么必须是def-clear且loop-free的path
        • loop-free: 没有重复结点

白盒测试 - 图22

  • 针对变量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)

  • 数据流图
    白盒测试 - 图23
  • 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> |

白盒测试 - 图24

  • 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

  • 控制流图

白盒测试 - 图25

  • 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 |