第七章 测试
? 基本概念
? 单元测试
? 集成测试
? 验收测试
? 设计测试方案
? 调试
? 软件可靠性
? 日立预测法
? 自动测试工具
基本概念
? 7.1.1 软件测试的目标
? 7.1.2 黑盒测试和白盒测试
? 7.1.3 软件测试的步骤
? 7.1.4 测试阶段的信息流
基本概念
? 软件测试的目标
? 测试是为了发现程序中的错误而执行程序的过

? 只能尽可能查错,不能证明程序中没有错
? 测试员与程序员不应是同一个人
基本概念
? 黑盒测试和白盒测试
? 黑盒测试 ----已经知道产品应该具有的功能,检
验每个功能是否都能正常使用 ----功能测试
? 白盒测试 ----已经知道产品内部工作过程,检验
产品内部动作是否按规定正常使用 ----结构测试
基本概念
? 软件测试的步骤
? 模块测试
? 单元测试
? 子系统测试
? 测试模块的接口
? 系统测试
? 和子系统测试合称集成测试
? 验收测试
? 平行运行
基本概念
? 测试阶段的信息流
单元测试
? 7.2.1 单元测试考虑
? 7.2.2 单元测试过程
单元测试
? 单元测试考虑
? 模块接口
? 内部检查:传输参数的数目、属性、单位、次序
是否匹配;全程变量的定义是否一致;只做输入
的变元有无被修改
? 外部检查:打开、结束、关闭文件的操作;文件
和属性; I\O错误处理;输出拼写
? 局部数据结构
? 数据说明 (declaration);初始化与缺省值的设置;
变量名拼写;数据类型的相容性;上 \下溢出及
地址异常
单元测试
? 单元测试考虑
? 重要的执行通路 常见的错误
? 计算次序问题
? 不同类型混合运算(例:比较类型不同的量)
? 初值设置错误
? 精度问题(例:精度不够导致两变量不可能相等,
而程序中等待相等条件的出现)
? 表达式错误
? 循环终止条件错误(例:次数差 1,或陷入死循环)
单元测试
? 单元测试考虑
? 出错处理通路 常见的问题
? 输出的错误信息难以理解,不能确定错误位置
? 描述的错误与实际错误不符
? 处理之前系统已经干预
? 处理不正确
? 边界条件
? 单元测试中最后,也可能是最重要的任务,因为软
件常在其边界失效
单元测试
? 单元测试过程
? 代码审查
? 测试软件
集成测试
? 非渐增式测试
? 分别测试每个模块,再放在一起结合成所要的程序
? 渐增式测试
? 将下一个要测试的模块同以测试好的模块放在一起
测试,类推结合成所要的程序
? 分为 自顶向下 和 自底向上 两种方法
集成测试
? 两者比较
? 渐增式测试 可以较早发现模块间的接口错误
? 非 渐增式测试 最后才组装,因此错误发现得晚。
? 非渐增式测试 中发现错误后难以诊断定位
? 渐增式测试 中,出现的错误往往跟最新加入的模块
有关。
? 渐增式测试 在不断集成的过程中使模块不断在新的
条件下受到新的检测,测试更彻底。
? 渐增式测试 较 非 渐增式测试 费时。
? 非渐增式测试 可以同时并行测试所有模块,能充分
利用人力。
集成测试
? 自顶向下结合
? 步骤
集成测试
? 自顶向下结合
? 步骤
? 测试顶端模块,用存根程序 (stub)代替直接附属的下
层模块
? 根据深度优先或宽度优先的策略,每次用一个实际
模块代换一个 stub
? 在结合进一个模块的同时进行测试
? 回归测试 -------全部或部分地重复以前做过的测试
集成测试
? 自顶向下结合
? 优点
? 在早期即对主要控制及关键的抉择进行检验
? 问题
? Stub只是对低层模块的模拟,测试时没有重要的数
据自下往上流,许多重要的测试须推迟进行,而且
在早期不能充分展开人力
集成测试
? 自底向上结合
? 步骤
集成测试
? 自底向上结合
? 步骤
? 把低层模块组合成族,每族实现一个子功能
? 用驱动程序 (Driver)协调测试数据的 I\O,测试子功
能族
? 去掉 Driver,自下而上把子功能族合成更大的子功能

集成测试
? 不同集成测试策略的比较
? 改进的自顶向下测试方法
? 混合法
? 两种策略的优、缺点刚好互补,但单用其中任一种
都不实际,通常根据软件的特点将二者混用
验收测试
? 7.4.1 验收测试的范围
? 7.4.2 软件配置复查
验收测试
? 验收测试的范围
? 某些已经测试过的纯粹技术性的特点可能不需要再
次测试
? 对用户特别感兴趣的功能或性能,可能需要增加一
些测试;
? 通常主要使用生产中的实际数据进行测试;
? 可能需要设计并执行一些与用户使用步骤有关的测

? 软件配置复查
设计测试方案
? 7.5.1 逻辑覆盖
? 7.5.2 等价划分
? 7.5.3 边界值分析
? 7.5.4 错误推测
? 7.5.5 实用测试策略
设计测试方案
? 逻辑覆盖 ----------适用于白盒测试
? 语句覆盖,每个语句至少执行一次
? 判定覆盖:在语句覆盖的基础上,每个判定的每个
分支至少执行一次
? 条件覆盖:在语句覆盖的基础上,使每个判定表达
式的每个条件都取到各种可能的结果
? 判定 /条件覆盖:即 判定覆盖 ?条件覆盖
? 条件组合覆盖:每个判定表达式中条件的各种可能
组合都至少出现一次
? 点覆盖;边界覆盖;路径覆盖




设计测试方案
? 逻辑覆盖
? 语句覆盖
A=2,B=0,X=4
若 AND错写为 OR,
或 X>1错写为 X<1,
则错误无法由上例
测出。
入口
A > 1
AND B=0
T
A=2
OR X > 1
T
X = X / A
X = X + 1
返回
F
F
设计测试方案
? 逻辑覆盖
? 判定覆盖
A=3,B=0,X=3
A=2,B=1,X=1
若 X>1错写为 X<1
,仍然无法被测出
入口
A > 1
AND B=0
T
A=2
OR X > 1
T
X = X / A
X = X + 1
返回
F
F
设计测试方案
? 逻辑覆盖
? 条件覆盖
? A=2,B=0,X=4
(满足 A>1,B=0; A=2,X>1)
? A=1,B=1,X=1
(满足 A? 1,B?0; A ?2,X?1)
入口
A > 1
AND B=0
T
A=2
OR X > 1
T
X = X / A
X = X + 1
返回
F
F
设计测试方案
? 逻辑覆盖
? 条件组合覆盖
? A>1,B=0; A>1,B? 0
? A?1,B=0; A?1,B? 0
? A=2,X>1; A=2,X? 1
? A ? 2,X>1; A ? 2,X? 1
? 仍有未测到的路径
? ( T,F)
入口
A > 1
AND B=0
T
A=2
OR X > 1
T
X = X / A
X = X + 1
返回
F
F
设计测试方案
? 逻辑覆盖
? 边覆盖
A=3,B=0,X=3
(T,F)
A=2,B=1,X=1
(F,T)
入口
A > 1
AND B=0
T
A=2
OR X > 1
T
X = X / A
X = X + 1
返回
F
F
设计测试方案
? 逻辑覆盖
? 路径覆盖
A=1,B=1,X=1
(F,F)
A=1,B=1,X=2
(F,T)
A=3,B=0,X=1
(T,F)
A=2,B=0,X=4
(T,T)
入口
A > 1
AND B=0
T
A=2
OR X > 1
T
X = X / A
X = X + 1
返回
F
F
设计测试方案
? 等价划分
? 划分经验
? 如果规定了输入值的范围,则可划分出一个有效的
等价类 (输入值在此范围内 ),两个无效的等价类 (输
入值小于最小值或大于最大值 )
? 如果规定了输入数据的个数,则类似地也可以划分
出一个有效的等价类和两个无效的等价类
? 如果规定了输入数据的一组值,而且程序对不同输
入值做不同处理,则每个允许的输入值是一个有效
的等价类,此外还有一个无效的等价类 (任一个不允
许的输入值 )
设计测试方案
? 等价划分
? 划分经验
? 如果规定了输入数据必须遵循的规则,则可以划分
出一个有效的等价类 (符合规则 )和若干个无效的等价
类 (从各种不同角度违反规则 )
? 如果规定了输入数据为整型,则可以划分出正数、
零和负整数等三个有效类
? 如果程序的处理对象是表格,则应该使用空表,以
及含一项或多项的表
设计测试方案
? 等价划分
? 有效输入的等价类有
? (1)1— 6个数字字符组成的数字串 (最高位数字不是零 )
? (2)最高位数字是零的数字串;
? (3)最高位数字左邻是负号的数字串;
? 无效输入的等价类有
? (4)空字符串 (全是空格 );
? (5)左部填充的字符既不是零也不是空格;
? (6)最高位数字右面由数字和空格混合组成;
? (7)最高位数字右面由数字和其他字符混合组成;
? (8)负号与最高位数字之间有空格;
设计测试方案
? 等价划分
? 合法输出的等价类有
? (9)在计算机能表示的最小负整数和零之间的负整数;
? (10)零;
? (11)在零和计算机能表示的最大正整数之间的正整数;
? 非法输出的等价类有
? (12)比计算机能表示的最小负整数还小的负整数
? (13)比计算机能表示的最大正整数还大的正整数
设计测试方案
? 边界值分析
? 程序最容易在边界发生错误
? 通常与等价划分结合进行。
设计测试方案
? 错误推测
? 思路
? 列出可能有的错误
? 列出容易发生错误的特殊情况
? 根据
? 直觉、经验
? 工具:常见错误清单、判定表等
设计测试方案
? 实用测试策略
? 在任何情况下都应该使用 边界值分析 的方法
? 必要时用 等价划分法 补充
? 必要时再用 错误推测法 补充
? 对照程序逻辑,检查测试方案。可根据对程序
可靠性的要求采用不同的 逻辑覆盖标准,必要
时补充一些测试方案
调试
? 7.6.1 调试技术
? 7.6.2 调试策略
调试
? 调试技术
? 输出存储器内容
? 以八进制或十六进制的形式印出存储器的内容。
? 缺点
? 输出信息量极大,不易解读且大多无用
? 输出的是程序在某一时刻的静态情况,且往往不是出错
时的状态
调试
? 调试技术
? 打印语句
? 缺点
? 可能输出大量需要分析的信息,对于大型程序系统来说情
况更是如此
? 必须修改源程序才能插入打印语句,但是这可能改变了关
键的时间关系,从而既可能掩盖错误,也可能引进新的错
误。
调试
? 调试策略
? 试探法
? 凭经验猜测。
? 回溯法
? 由症状 最先出现的地方,沿 控制流 向回检查。适用于小型程序。
? 对分查找法
? 在关键点插入变量的正确值
? 归纳法
? 从错误症状中找出规律,推断根源
? 演绎法
? 普通 ? 特殊
? 从假设中逐步排除、精化,从而导出错误根源
软件可靠性
? 7.7.1 基本概念
? 7.7.2 估算平均无故障时间的方法
? 7.7.3 程序正确性证明
软件可靠性
? 基本概念
? 可靠性
? 程序在给定的 时间间隔内,按照说明书的规定,成
功地运行的概率。
? 可用性
? 程序在给定的 时间点,按照说明书的规定,成功地
运行的概率
? 正确性
? 程序的功能正确
软件可靠性
? 估算平均无故障时间的方法
? 平均无故障时间 MTTF=
? K为经验常数(典型值约在 200左右);
? ET为测试前故障总数;
? IT为程序长度(机器指令总数);
? ?为测试(包括调试)时间;
? EC(? )为时间从 0至 ?期间改正的错误数
)) / I( τE/IK ( E
1
TCTT ?
软件可靠性
? 程序正确性证明
? 正确性证明只证明程序功能正确,但不能验证
动态特性;
? 证明过程本身也可能发生错误
日立预测法
? 7.8.1 测试完成率模型
? 7.8.2 错误发现率模型
? 7.8.3 使用日立预测法的步骤
日立预测法
? 测试完成率模型
100%
50% 100% 测试时间使用率 =
所用时间 / 总时间第一
阶段
第二
阶段
第三
阶段
测试用例完成率 = 已完成用例 / 全部用例 工程的成败取
决于第一阶段
向第二阶段转
移断点的位置,
一般成功的工
程其转折点位
于 15%;若超
过 55%则破产
不可避免
日立预测法
? 错误发现率模型
错误发现率 = 单位时间内发现的错误数
时间峰值时间





失败的
工程
极坏的工程
刚过峰值点后
曲线的导数关
系到工程的成
败。若导数值
大于 - 0.3,则
失败不可避免
自动测试工具
? 7.9.1 测试数据生成程序
? 7.9.2 动态分析程序
? 7.9.3 静态分析程序
? 7.9.4 文件比较程序
自动测试工具
? 测试数据生成程序
? 功能
? 自动生成大量输入数据
? 用途
? 测试系统在实际环境中的性能(例如测试数据库管
理系统)
? 自动校核系统输出 (若输出数据的语法可以被形式地
说明 )
? 缺点
? 不能自动生成预期的输出,因此用途有限。
自动测试工具
? 动态分析程序
? 功能
? 分析程序中每个语句的执行次数
? 组成
? 检测部分:插入检测语句,负责收集、整理语句执行次数
? 显示部分:以容易理解的形式印出收集的信息
? 用途
? 发现测试中没有执行的语句,以增加相应的测试用例
? 发现不按要求终结的循环
? 发现不应执行却执行了的代码,及应执行而未执行的代码
自动测试工具
? 静态分析程序
? 不执行程序,仅扫描程序的正文,从中寻找可
能导致错误的异常情况
? 文件比较程序
? 主要步骤
? 建立一个文件存放预期的正确结果
? 执行测试,将输出数据存进另一个文件
? 使用文件比较程序来比较上述两个文件,印出两者
之差异