软件测试


1 测试概述

1.1 PIE模型

1.1.1 缺陷,错误,失败(fault, error,failure)

  • 软件缺陷:软件中的静态故障(一般指错误代码)
  • 软件错误:错误的内部状态(中间状态),是某些缺陷的表现(比如中间变量显示与预期不同的值)
  • 软件失败:与需求或预期结果的不同的外部的、不正确的结果

1.1.2 PIE模型

概念:使用户或测试人员观测到failure的过程。

三个必要条件:

  • 执行/可达Execution/Reachability:必须到达程序中包含缺陷的一个或多个位置(必须执行到fault位置)
  • 感染Infection:程序的状态必须不正确(必须出现error)
  • 传播Propagation:感染状态必须传播,以导致程序的某些输出不正确(必须出现failure)

1.1.3 讨论

Q:是否存在没有被任何测试用例发现的缺陷?

A: 存在。因为可能所有测试用例到无法执行到含缺陷的位置。

Q:如何判断缺陷?

A:缺陷的判断具有主观性,某位置修改后可以使测试用例通过的,都可视为缺陷。

1.2 术语

1.2.1 测试用例Test case

PS: 测试用例一定包含输出,除非只要求测试输入。

  • 测试输入Test Input:测试数据
  • 测试输出Test Oracle:预期输出
  • 其他:测试环境Environment

1.2.2 测试夹具Test fixture

测试执行所需要的固定环境。

1.2.3 测试套件Test suite

测试用例的集合。

  • 通常这些测试用例共享类似的先决条件和配置
  • 通常可以按顺序一起运行
  • 不同的测试套件用于不同的目的:特定的平台,特定的功能,性能…

1.2.4 测试脚本Test script

自动运行一系列测试用例或测试套件的脚本。

1.2.5 测试驱动Test driver

可以加载一组测试用例或测试套件的软件框架。

  • 它还可以处理预期输出和实际输出之间的配置和比较。

1.2.6 测试充分性Test adequacy

判断测试是否可以停止。

  • 充分性标准:让我们判断一款软件的一组测试数据是否充分性的规则。
  • 举例:测试覆盖Test coverage

1.2.7 测试Testing 与 调试Debugging

  • 测试发现bug
  • 调试修改bug

1.2.8 验证Verification 与 确认validation

  • 验证:从开发者的角度(内部)来验证产品的需求、架构设计等方面和用户要求的一致。即开发的产品是否正确。
  • 确认:从用户的角度(外部)来验证产品和自己想要的一致。即是否开发出正确的产品。

1.2.9 静态测试Static Testing 与 动态测试Dynamic Testing

  • 静态测试:不执行程序
  • 动态测试:执行程序

1.2.10 黑盒测试Black-box Testing 与 白盒测试White-box Testing

  • 黑盒测试:不使用源码
  • 白盒测试:使用源码
  • 灰盒测试Gray-box Testing:黑盒测试+白盒测试

1.2.11 测试级别Testing level

  • V模型:单元测试、集成测试、子系统测试、系统测试、验收测试

image-20210525141618533

1.2.12 测试过程Test process

image-20210525142207752

1.3 缺陷复查

1.3.1 Bug

出现failure代表存在bug。

1.3.2 缺陷判定

缺陷判定原则是修改之后原本失败的测试用例可以通过。

  • 即便只有一个用例通过或者即便仍然存在缺陷可能导致其他测试用例不通过。
  • 一个缺陷对应一个测试用例,而不是一行代码(代码行数)。

1.3.3 bug修复判定

bug是否修复的标准是测试用例是否全部通过。

1.3.4 缺陷干扰

不同缺陷之间相互干扰,造成部分测试用例通过的假象。

2 单元测试

2.1 测试粒度Granularity of Testing

  • 单元测试:测试每一个单独的模块
  • 集成测试:测试不同组件之间的相互作用
  • 系统测试:开发者测试整个系统
  • 验收测试:用户基于需求进行系统的确认。

2.2 单元测试范围

  • 软件的基本模块:一个函数或一个类或一个组件。
  • 典型的问题出现在:本地数据结构、算法、边界条件、错误处理。

2.3 为什么单元测试?

分而治之的方法。

  • 将系统拆分为多个单元
  • 单独调试单元
  • 缩小可能存在错误的地方
  • 不想追逐其他单元的错误

2.4 如何单元测试?

分层构建系统:

  • 从不依赖其他部分的类开始。
  • 在已经测试过的类上继续测试。

好处:

  • 避免编写模拟类。
  • 在测试模块时,它所依赖的模块是可靠的。

2.5 单元测试框架

  • xUnit
  • JUnit

3 白盒测试

3.1 测试中的图形

3.1.1 图的基本概念

3.1.1.1 图的一般定义

图一般用G = (V, E)表示

  • V:一组有限的非空顶点。
    • V0:初始顶点的集合。
    • Vf:最终顶点的集合。
  • E:一组变(成对的顶点)。

3.1.1.2 讨论

Q:单独的顶点是图吗?

A:是的。

Q:E(边集合)可不可以无限。

A:不可以,因为顶点是有限的。

3.1.1.3 路径Path

一组连通的顶点集合,每对顶点都是一条边。

image-20210525170441304

  • 长度:边的数目(顶点数-1),如上为3

  • 子路径:含有父路径中部分顶点的一条路径(一定要是路径)。

    • V2, V4, V6可,V1, V2, V6不可
  • 测试路径:从初始顶点开始,终止最终顶点的一条路径。

    • 如上,共有4条测试路径。

3.1.1.4 测试和测试路径

术语表示:

  • path(t):执行测试用例 t 的测试路径。
  • path(T):执行测试用例集 T 的测试路径集。
  • 每一个测试用例有且只有一条测试路径。

测试路径可以代表测试用例的执行。

  • 一些测试路径可以执行多个测试用例。

3.2 图覆盖准则

3.2.1 可达Reach

  • 当存在一条路径从v1开始到v2结束时,称v1可达v2。

  • 当存在一条路径从v1开始到图G‘的其中一个顶点时,称v1可达G’。

  • 语法可达Syntactic reach:在图中存在一条路径。

  • 语义可达Semantic reach:存在可以执行该路径的测试用例。。

  • if(true) {}

    else { } // 此处语义不可达,语法可达。

3.2.2 覆盖Cover

  • 顶点v在路径p中:p覆盖v
  • 边e在路径p中:p覆盖e
  • 子路径p‘在路径p中:p覆盖p’

3.2.3 测试标准

  • 测试需求Test Requirements(TR):描述测试路径的属性。
  • 测试标准Test Criterion(TC):定义测试需求的规则。
  • 满足Satisfaction:给定标准C的一组测试需求TR,当且仅当对于TR中的每个测试需求tr,在path(T)中存在满足该测试需求的测试路径p时,称一组测试T在图形上满足标准C。

3.3 结构覆盖Structural Coverage

在图上仅根据顶点和边定义。

3.3.1 顶点覆盖Vertex Coverage(VC)

当且仅当对于V中的每个语法上可达的顶点v,在path(T)中存在一条路径p覆盖v时,测试集T满足图G上的顶点覆盖。即测试需求集TR包含G中的每个可达顶点。

3.3.2 边覆盖Edge Coverage(EC)

当且仅当对于E中每个语法可达的边e,在path(T)中存在一条路径p覆盖e时,测试集T满足图G的边覆盖。即测试需求集TR包含G中的每个可达边。

image-20210525180335164

3.3.3 多边覆盖

  • **边对覆盖Edge-Pair coverage(EPC)**:TR包含图G内每条可达的长度不超过2的路径。
  • **n路径覆盖范围n-Path Coverage(nPC)**:TR包含图G内每条可达的长度不超过n的路径。
  • **完全路径覆盖Complete Path Coverage(CPC)**:TR包含G中的所有路径。
  • VC(n=0), EC(n=1), EPC(n=2), CPC(n=∞)

3.3.4 讨论

Q:当一个图只有长度为n2的路径时,怎么求n1PC,且n1 ≥ n2。

A:没有长度大于n2的路径。举例:只有孤立顶点的图没有边覆盖。只有只有一条边的图的EPC没有长度为2的路径。

3.3.5 包含Subsume

  • C1包含C2,用C1≥C2表示,且对于任何T,如果T满足C1则意味着T满足C2。

  • 当 n1≧n2,n1PC≧ n2PC

  • 注意:C1≥C2并不意味着满足C1的T1可以检测到满足C2的T2检测到的任何故障。

3.3.6 结构覆盖例子

image-20210525181913478

  • TR和Test Path都不包含重复路径(包括父路径和子路径)。

3.4 控制流图与其覆盖

3.4.1 代码覆盖率

  • 语句覆盖Statement coverage
  • 分支覆盖Branch coverage
  • 路径覆盖Path coverage

3.4.2 控制流图Control Flow Graph

顶点:

  • 语句
  • 基本块:只有一个入口和一个出口的语句
  • 函数
  • 模块

边:

  • 跳转
  • 回调

3.4.2.1 CFG: if

image-20210525184024994

3.4.2.2 CFG: if-return

image-20210525184052021

3.4.2.3 CFG: while

image-20210525184206603

3.4.2.4 CFG: do

image-20210525184318467

3.4.2.5 CFG: for

image-20210525184427027

3.4.2.6 CFG: break and continue

image-20210525184647596

3.4.2.7 CFG: switch

image-20210525184725035

3.4.2.8 CFG举例

image-20210525184807598

3.4.3 基于控制流图的覆盖率

3.4.3.1 语句覆盖

测试涵盖的语句百分比。

3.4.3.2 分支覆盖

测试覆盖的分支百分比。

  • 考虑每个条件语句的false和true分支。

image-20210525185217134

3.4.3.3 路径覆盖

测试覆盖的路径百分比。

  • 考虑所有可能的程序执行路径

3.4.3.4 比较

image-20210525185734980

  • 如果可以实现100%的分支覆盖,可以实现100%的语句覆盖。

  • 如果可以实现100%的路径覆盖,可以实现100%的分支覆盖。

  • 但是路径覆盖对于实际程序可能是不可行的。

3.4.3.5 效率

  • 大约65%的错误可以在单元测试中发现
  • 单元测试以控制流测试方法为主导
  • 语句和分支测试在控制流测试中占主导地位

3.4.3.6 局限性

即便达到100%覆盖,仍然可能存在bug。

3.5 主路径覆盖Prime Path Coverage

3.5.1 简单路径Simple Path

除了第一个和最后一个顶点可能相同,如果其他没有顶点出现多次,则从顶点ni到nj的路径是简单的。

  • 没有内部循环
  • 循环是一条简单的路径

3.5.2 主路径Prime Path

一种简单路径,它不是任何其他简单路径的子路径。

  • 最长简单路径
  • 一定不包括单顶点路径,除非是单点图

3.5.2.1 主路径覆盖Prime Path Coverage(PPC)

TR包含G中的每个主路径。

  • PPC不包含EPC,因为EPC中存在单顶点循环路径(以一个顶点为开始和结束的循环路径)。

3.5.2.2 往返Round Trip

往返路径Round-Trip Path:在同一顶点上开始和结束的主要路径。

  • 简单往返覆盖(SRTC):TR包含G中每个可达顶点至少一条往返路径,该顶点从往返路径开始并结束。
  • 完全往返覆盖(CRTC):TR包含G中每个可达顶点的所有往返路径。

这些条件会忽略不在往返中的顶点和边,也就是说,它们不包含边对,边或顶点覆盖率。

3.5.3 简单路径和主路径举例

  • 简单路径

image-20210525200240988

  • 主路径

image-20210525200313516

3.5.4 讨论

Q:如何生成测试覆盖所有主路径?

A:符号执行或者可以控制程序运行路径。

Q:部分主路径都是不可行的吗?

A:是,比如一些循环路径。

  • 控制流图练习

image-20210525200638366

image-20210525200653805

3.6 基本路径覆盖Basic Path Coverage

  • 针对单入口,单出口控制流图
  • 在程序控制流图的基础上,通过分析控制构造的环路复杂性,导出基本可执行路径集合,从而设计测试用例的方法。

3.6.1 独立路径Independent Path

通过系统的路径仅在其包含的某些顶点或边未被其他路径覆盖的情况下才与其他路径无关。

  • 和其他的独立路径相比,至少引入一个新处理语句或一个新判断的程序通路。

3.6.2 线性独立路径Linearly Independent Path

线性独立路径数:线性独立路径的数量是该矩阵的秩。

  • 该矩阵的秩恰好是图的圈复杂度

  • 麦凯布的环复杂性McCabe’s Cyclomatic Complexity(CC):CC = E-V+2

3.6.3 McCabe的基础路径测试

  1. 生成控制流程图
  2. 计算圈复杂度
  3. 选择一组基本路径
  4. 生成基本路径的测试
  • 基本测试覆盖练习

image-20210525202010293

  • 0或1代表是否经过边。
  • 下面的式子表示为什么要去除set2的第三个。
  • 最终结果表示存在三条基本路径

所有路径测试 ≥ 基本路径测试 ≥ 分支测试。

3.7 数据流覆盖Data Flow Coverage

目标:尝试确保计算或使用的值正确。

3.7.1 Data Flow

  • 定义Define(def):变量的值存入内存(赋值)的地方。

  • 使用Use:变量的值被访问(读取)的地方。

  • defs中给出的值应至少达到一种,某些或所有变量才可能使用。

3.7.2 def集和use集

  • def (n) or def (e) :由顶点n或边e定义的变量集。
  • use (n) or use (e) :顶点n或边e使用的变量集。

3.7.3 读写配对DU Pair

一对位置(li,lj),使得变量v在li处定义并在lj处使用。

3.7.4 清晰路径Def-clear

  • Def-clear:如果v在路径中的任何顶点或边上均未赋予其他值,则对于变量v,从li到lj的路径是清晰的。
  • 可达Reach:如果存在从li到lj的相对于v的清晰路径,则li处的v的def可达lj处的use。

3.7.5 DU路径

从v的定义到v的使用,相对于v而言清晰的简单子路径。

  • du (ni, nj, v) : 从ni到nj的DU路径的集合。

  • du (ni, v) : 从ni开始的DU路径的集合。

3.7.6 数据覆盖标准Data Flow Coverage Criteria

  • 全定义覆盖All-defs coverage(ADC):对于每组DU路径S = du(n,v),TR在S中至少包含一条路径d。

  • 全使用覆盖All-uses coverage(AUC):对于每组DU路径S = du(ni,nj,v)的每组du路径,TR至少包含S中的一条路径d。

  • 全du路径覆All-du-paths coverage(ADUPC):对于每个集合S = du(ni,nj,v),TR包含S中的每个路径d。

  • 数据流测试举例

image-20210525204513725

3.8 事件流图(Event Flow Graph)

定义:事件流图(EFG)是一个三元组M =⟨V,I,E⟩,其中:

  • V是代表对象所有事件的一组顶点。
  • I⊆V是一组初始顶点。
  • E⊆V×V是顶点之间的一组边。 (vi,vj)∈E 当且仅当 vj可以在vi之后立即执行

3.8.1 覆盖标准

  • 事件覆盖
  • 事件对覆盖
  • 路径覆盖

3.8.1 事件流图例子

image-20210525205735012

  • 对于界面而言,只考虑事件是否可以连续执行(点击),可以即连通,不考虑功能隐含逻辑(如必须先复制再粘贴,事实上可以不复制直接粘贴,只是值为空)。

3.9 变异测试Mutation Testing

3.9.1 等价变异体

可能存在尚无法杀死的突变体(意思是通过所有测试用例),这些被称为等价突变体。尽管在语法上有所不同,但通过测试无法区分这些突变体。因此,必须“手动”检查它们。

3.9.2 变异评分Mutation Score

一组测试用例的突变评分是测试数据杀死的非等价突变体的百分比。
变异分数= 100 * K / T
K =被杀死的突变体数量
T =突变体总数
E =等效突变体的数量
如果一组测试用例的突变得分为100%,则这组测试用例具有足够的变异性。

3.9.3 变异测试基于的假设

  • 称职程序员假设Competent Programmer Hypothesis(CPH)
    被测模块已经由称职的程序员或设计师编写。 因此,如果模块不正确,则与正确模块的区别最多为几个小故障。
  • 耦合效应Coupling Effect(CE)
    一个简单的错误产生往往是由于一个单一的变异(例如句法错误),而一个庞大复杂的错误往往是由于多处变异所导致。复杂变异体往往是由诸多简单变异体组合而成。

3.9.4 结论

  • 突变是单个语法(单语句)。
  • 变异测试用于评估测试用例的充分性

3.10 逻辑覆盖

3.10.1 判定覆盖Decision Coverage

覆盖判定的正确与错误。

3.10.2 条件覆盖Condition Coverage

覆盖每个条件的对与错(每个条件的正确与错误至少取一次)。

3.10.3 包含关系

C1 包含 C2, 表示为 C1 ≥ C2

  • DC ≥ SC
  • CC not ≥ SC
  • DC not ≥ CC, CC not ≥ DC

3.10.4 条件判定覆盖Condition/Decision Coverage (C/DC)

结合 DC and CC,既覆盖判定的正确与错误,又覆盖所有条件的对与错。

  • C/DC ≥ CC
  • C/DC ≥ DC

3.10.5 多条件覆盖Multiple Condition Coverage

  • 多条件覆盖(MCC):设计足够多的测试用例,使得每个判定中条件的各种可能组合都至少出现一次。

  • 完全覆盖一个布尔表达式的多条件覆盖测试用例基本上由该表达式的逻辑运算符真值表给出。

  • 如果有n个condition,则有2^n种测试用例。

3.10.6 修正条件判定覆盖Modified Condition/Decision Coverage

在一个程序中每一种输入输出至少得出现一次,在程序中的每一个条件必须产生所有可能的输出结果至少一次,并且每一个判定中的每一个条件必须能够独立影响一个判定的输出,即在其他条件不变的前提下仅改变这个条件的值,而使判定结果改变。

  • 每一个条件产生所有可能的输出结果:
    • A可以取到T和F
  • 独立影响结果:
    • A的取值相反,结果相反。
    • A为T,des为T/F
    • A为F,des为F/T

MC/DC被设计用于不包含短路特性的逻辑运算符的语言。C,C ++和Java中的短路逻辑运算符仅在其结果会影响包围决策时评估条件。MC / DC将受到程序中决策结构的影响。

image-20210525221812537

  • 如果将MC/DC用于含短路特性的语言中,需要分解语句。

3.10.7 讨论

Q:请构造一个条件,其中条件没有独立的结果。

A:a < 0 && a> 0

Q:测试用例一般的个数?n代表条件个数

A:DC——2,CC——2*n,MC/DC——2*n,MCC——2^n

5 黑盒测试

5.1 等价类划分Equivalence Partitioning

分区必须满足两个属性:

  • 块必须成对不相交(无重叠)
  • 这些块一起覆盖了域D(完整)

5.1.2 基于接口的方法Interface-based approach

  • 直接从各个输入参数开发特性

  • 机械地考虑每个参数的分割

  • 这是一种简单的建模技术,主要依靠语法

  • 忽略参数之间的关系

  • 示例:TriTyp 判断三角形类型程序的输入域划分

image-20210525234752257

image-20210525233207479

5.1.3 基于功能的方法Functionality-based approach

  • 识别与预期功能相对应的特征

  • 需要测试人员进行更多的设计工作

  • 可以合并领域和语义知识

  • 可以使用参数之间的关系

  • 建模可以基于需求而不是实现

  • 相同的参数可能会出现在多个特征中,因此很难将值转换为测试用例

  • 示例:TriTyp 判断三角形类型程序的输入域划分

    • 前两个表征基于语法参数及其类型
    • 语义级别的表征可以使用以下事实:三个整数代表一个三角形

image-20210525234135785

image-20210525234209631

  • scalene[‘skeɪli:n]不等边,Isosceles[aɪ‘sɒsɪli:z]等腰,equilateral[ˌi:kwɪ‘lætərəl]等边

5.2 边界值分析 Boudary-Value Analysis

5.2.1 选择边界值

具有等效类[Min,Max]的输入变量:

  • Min
  • Min+
  • Nom
  • Max-
  • Max

5.2.2 弱边界分析Weak Boundary Analysis

5.2.2.1 弱一般边界分析

image-20210526001536543

5.2.2.2 弱健壮边界分析

考虑无效值,具有等价类[Min,Max]的输入变量:

  • Min-
  • Min
  • Min+
  • Nom
  • Max-
  • Max
  • Max+

image-20210526000209811

image-20210526000303444

  • 例题

image-20210526000657475

5.2.3 强边界分析StrongBoundary Analysis

5.2.3.1 强一般边界分析

image-20210526001750886

image-20210526000510493

5.2.3.2 强健壮边界分析

image-20210526001719192

  • 例题

image-20210526003017607

5.2.4 总结边界值分析

弱”是指含单缺陷假设(失效极少是由两个或两个以上的缺陷同时引起的),“强”是指含多缺陷假设(失效是由两个或两个以上的缺陷同时引起的);“一般”是指不考虑无效值。“健壮是指考虑无效值”弱一般等价类测试用例通过使用一个测试用例中的每个有效等价类(区间)的代表值来实现(常以对称方式来标识这些测试用例,且注意单边假设作用,即每次只在一个变量中取边界值,其余变量取一般值);强一般等价类测试用例通过每个独立变量的有效等价类的笛卡尔积来实现。

5.3 组合测试Combinatorial Testing

5.3.1等价类测试

  • 弱等价类测试

image-20210526013654239

  • 强等价类测试

image-20210526013717703

5.3.2 成本效益测试Cost Effective Testing

5.3.2.1 组合测试

  • 全排列组合测试

image-20210526020211344

  • 成对测试(2-wise)

image-20210526020246697

其中,A和C配对全排列组合(笛卡尔积),B和D配对全排列组合(笛卡尔积),因为B和D配对的排列组合更多,以B和D的排列组合个数为总的用例个数。

  • t-wise/t-ways 组合测试

image-20210526020429657

其中,A、B、C配对全排列组合(笛卡尔积),B、C、D配对全排列组合(笛卡尔积),因为B、C、D配对的排列组合更多,以B、C、D的排列组合个数为总的用例个数。

5.3.2.2 组合测试分析

  • 固定强度组合测试:

    • 成对测试

    • t-ways组合测试

  • 可变强度组合测试

  • 关键问题

    • 所有组合采样
    • 不考虑输入的特殊信息

5.4 测试中的缺省选项

5.4.1 基本选项

image-20210526021842542

  • 缺省值可以按照等价类划分法选取
  • 每一个测试用例只修改一个变量值为非缺省值(标红位置),其他变量仍为缺省值,加上均为缺省值的用例,一共5 + 1 = 6 个测试用例。

5.4.2 多基本选项

image-20210526022152540

  • 缺省值可以按照等价类划分法选取,可以为多个。
  • 每一个测试用例只修改一个变量值为非缺省值(标红位置,注意当前的缺省值默认为1个,即D3虽然属于D的缺省值,但是在上部分的测试用例中已经选定了一个缺省值,因而在上半部分D3暂时归为非缺省值),其他变量仍为缺省值,加上均为缺省值的用例,但是因为存在部分变量有多个缺省值,需要进行缺省值的全排列组合(笛卡尔积),一共 (5 + 1)*2 = 12 个测试用例。公式推导:测试用例个数 = ((变量取值个数 - 变量个数)+1)* 缺省值的全排列组合个数。

5.5 测试约束

约束指的是不能出现的变量取值组合。以下是解决测试约束的方法。

5.5.1 合并输入变量

image-20210526022916828

5.5.2 约简输入域

image-20210526023035222

5.5.3 修改测试用例

image-20210526023212700

  • 将不能出现的测试用例化为其他测试用例。

5.6 决策表

5.6.1 决策表组成

  • 条件桩—列出问题的所有条件
  • 条件项—针对条件桩中条件列出所有可能的取值
  • 动作桩—列出问题规定的可能采取的操作
  • 动作项—指出条件项各取值情况下应采取的动作

任何一个条件组合的特定取值及相应要执行的动作为一条规则。在决策表中贯穿条件项和动作项的一列是一条规则。

5.6.2 决策表的生成

  • 有n个条件的决策表有2^n个规则(每个条件取真、假值)
  • 若表中有两条以上规则具有相同的动作,并且在条件项之间存在极为相似的关系,便可以合并
  • 合并后的条件项用符号“-”表示,说明执行的动作与该条件的取值无关,称为无关条件

5.6.3 例题—三角形类型决策表

image-20210526023642786

5.6.4 练习题

前一日函数DPreate是NextDate的逆函数,即给定一个月份、日期、年,会返回前一天的日期。

  • 年的取值在1812年到2017年
  • 日的取值在1日到31日之间
  • 月的取值在1到12月之间

image-20210526023737811

image-20210526023754123

image-20210526023813990

5.7 测试输出/测试预言Test Oracle

5.7.1 蜕变测试Metamorphic Testing

image-20210526024457613

  • 如果新的测试用例输出f(t(x))符合预期,不一定正确。

  • 但是,如果f(t(x))与预期不符,则f(x)或f(t(x))或两者都是错的。

  • 蜕变测试示例1

image-20210526024702050

  • 蜕变测试示例2

image-20210526024734109

  • 蜕变测试课后作业习题

image-20210526024853160

5.8 测试用例集约简Test Suite Reduction

目标:获得满足所有测试需求tr的最小测试用例子集。

5.8.1 贪心法

  • 每次取满足测试需求最多的测试用例t

image-20210526025228009

5.8.2 添加额外信息的贪心法

  • 每次取满足的测试需求增加最多的测试用例t

image-20210526025444861

5.8.3 距离最大贪心法

  • 前提:不知道每个用例满足的对应需求是什么

image-20210526030049260

  • 每次取与之前已选测试用例的汉明距离最大的测试用例t

image-20210526025944959

5.9 测试用例排序Test Case Prioritization

让“预计失败”用例提前测试,从而使发现bug时间提前。

5.9.1目标函数APFD(T)

image-20210526030744027

  • k:被测程序P中包含的故障数。

  • m:测试用例总数。

  • tfi:在测试集T中暴露出故障 i 的第一个测试的位置。

  • 例题

image-20210526031049223

image-20210526031125428

  • 普通贪心是每次选择满足tr最多的用例
  • 含附加信息的贪心是每次选择新增满足tr最多的用例

5.10 缺陷定位Fault Loaction

5.10.1 利用PIE模型

fault语句激发failure,利用2个单缺陷测试用例(一个测试用例只含一个failure)的fault语句求交,定位fault。

5.10.2 基于频谱的缺陷定位Spectrum-based Fault Localization

使用程序频谱执行过程中程序行为的表示。

image-20210526031849071

  • 在失败的测试案例中经常发生的程序元素可能包含错误。

  • 在通过的测试用例中经常发生的程序元素很可能不包含任何错误。

  • 目标函数计算公式,本质是求aef

image-20210526032142240

  • 举例

image-20210526032237405

  • 最后按可能性排序,得出fault最有可能存在的位置

image-20210526155107835

7 集成测试与系统测试

7.1 系统集成的模式与方法

7.1.1 集成测试的模式

  • 非渐增式测试模式:先分别测试每个模块,再把所有模块按设计要求放在一起结合成所要的程序,如大棒模式。
  • 渐增式测试模式:把下一个要测试的模块同已经测试好的模块结合起来进行测试,测试完以后再把下一个应该测试的模块结合进来测试。
测试开销 发现模块间接口错误 诊断难易
非渐增式
渐增式

7.1.2 自顶向下和自底向上集成方法(渐增式集成)

  • 驱动程序/驱动模块(driver),用以模拟被测模块的上级模块。
  • 桩程序/桩模块(stub),也有人称为存根程序,用以模拟被测模块工作过程中所调用的模块(下级模块)。

7.1.2.1 自顶向下方法

image-20210526090959165

  • 主要优点是不需要测试驱动程序,能够在测试阶段的早期实现并验证系统的主要功能,而且能在早期发现上层模块的接口错误。
  • 主要缺点是需要存根程序,可能遇到与此相联系的测试困难,低层关键模块中的错误发现较晚,而且用这种方法在早期不能充分展开人力。

7.1.2.2 自底向上方法

image-20210526091135320

  • 与自顶向下方法的优缺点相反。

7.1.2.3 混合策略集成方法

image-20210526091413096

  • 对软件结构中较上层,使用的是“自顶向下”法;对软件结构中较下层,使用的是“自底向上”法,两者相结合。如三明治集成方法(主要缺点是:在真正集成之前每一个独立的模块没有完全测试过)。

7.1.3 大棒集成方法

image-20210526091607262

  • 采用大棒集成方法,先是对每一个子模块进行测试(单元测试阶段),然后将所有模块一次性的全部集成起来进行集成测试 。
  • 因为所有的模块一次集成的,所以很难确定出错的真正位置、所在的模块、错误的原因。
  • 非渐增式集合。

7.1.4 持续集成

通常系统集成都会采用持续集成的策略,软件开发中各个模块不是同时完成,根据进度将完成的模块尽可能早的进行集成,有助于尽早发现Bug,避免集成中大量Bug涌现。

而且容易定位Bug、修正Bug,最终提高软件开发的质量与效率

7.2 功能测试

根据产品特性和设计需求,验证一个产品的特性和行为是否满足设计需求。

7.2.1 相关测试类型

  • 正确性:产品功能是否与需求和设计文档一致
  • 可靠性:用户交互是否引发软件崩溃和其它异常
  • 易用性:软件产品完成特定任务的难易程度

7.3 回归测试

7.3.1 回归测试的目的

  • 所做的修改达到了预定的目的,如错误得到了改正,新功能得到了实现,能够适应新的运行环境等;
  • 不影响软件原有功能的正确性。

7.3.2 回归测试的方法

  • 再测试全部用例
  • 基于风险选择测试
  • 基于操作剖面选择测试
  • 再测试修改的部分

7.4 非功能性测试

7.4.1 性能测试

7.4.1.1 目的和需求

  • 目的:为了验证系统是否达到用户提出的性能指标,同时发现系统中存在的性能瓶颈,起到优化系统的目的。
  • 需求:用户对各项指标提出的明确需求;如果用户没有提出性能指标则根据用户需求、测试设计人员的经验来设计各项测试指标。(需求+经验)

7.4.1.2 性能指标

  • 不同的关注对象采用不同的性能的度量方法
  • 服务端性能采用CPU、内存等使用率来度量
  • 客户端性能通常根据系统处理特定用户请求的响应时间来度量
  1. 响应时间:

    • 服务端响应时间是指从请求发出开始到客户端接收到最后一个字节数据所消耗的时间。
    • 客户端响应时间是指客户端收到响应数据后呈现/响应用户所消耗的时间。
  2. 并发用户数:

    • 先确定业务场景,然后基于场景采用某些相应方法计算并发用户数

    • 在线用户数:用户同时在一定时间段的在线数量

      并发用户数:某一时刻同时向服务器发送请求的用户数

  3. 吞吐量:

    • 单位时间内处理的用户请求数量
    • 访问人数/天,页面数/秒,请求数/秒,处理业务数/小时,等等
  4. 性能计数器:

    • 描述系统性能的一些数据指标
    • 例如,内存使用率、CPU使用率、进程时间等都是常见服务器性能计数器

7.4.2 压力测试

压力测试(Stress test),也称为强度测试、负载测试。压力测试是模拟实际应用的软硬件环境及用户使用过程的系统负荷,长时间或超大负荷地运行测试软件,来测试被测系统的性能、可靠性、稳定性等。目标是找出性能瓶颈,从本质上来说,测试者是想要破坏程序。

  • 并发性能测试
  • 疲劳强度测试(采用系统稳定运行情况下能够支持的最大并发用户数或者日常运行用户数,持续执行一段时间业务)
  • 大数据量测试
    • 独立的数据量测试
    • 综合数据量测试(与其他压力测试相结合)

7.4.3 容量测试

容量测试目的是通过测试预先分析出反映软件系统应用特征的某项指标的极限值(如最大并发用户数、数据库记录数等),系统在其极限值状态下还能保持主要功能正常运行。容量测试还将确定测试对象在给定时间内能够持续处理的最大负载或工作量。

7.4.4 安全性测试

安全性测试是检查系统对非法侵入的防范能力。安全测试期间,测试人员假扮非法入侵者,采用各种办法试图突破防线。

7.4.5 可靠性测试

可靠性(Reliability)是产品在规定的条件下和规定的时间内完成规定功能的能力,它的概率度量称为可靠度。

三要素:

  • 规定的时间
  • 规定的环境条件
  • 规定的功能

成熟性度量可以通过错误发现率DDP(Defect Detection Percentage)来表现。在测试中查找出来的错误越多,实际应用中出错的机会就越小,软件也就越成熟。

DDP=测试发现的错误数量/已知的全部错误数量

7.4.6 容错性测试

容错性测试是检查软件在异常条件下自身是否具有防护性的措施或者某种灾难性恢复的手段。如当系统出错时,能否在指定时间间隔内修正错误并重新启动系统。容错性测试包括两个方面:

  • 输入异常数据或进行异常操作,以检验系统的保护性
  • 灾难恢复性测试

7.5 验收测试

7.5.1 验收测试的过程和主要内容

**验收测试(Acceptance Test)**:在软件产品完成了功能测试和系统测试之后、产品发布之前所进行的软件测试活动它是技术测试的最后一个阶段,也称为交付测试。

测试内容

验证系统是否达到了用户需求规格说明书(可能包括项目或产品验收准则)中的要求,测试试图尽可能地发现软件中存留的缺陷,从而为软件进一步改善提供帮助,并保证系统或软件产品最终被用户接受。

7.5.2 产品规格说明书的验证

  • 产品规格说明书的审核
  • 产品规格说明书的验证

7.5.3 用户界面和可用性测试

  • 用户界面的7要素:
    • 符合标准和规范
    • 直观性
    • 一致性
    • 灵活性
    • 舒适性
    • 正确性
    • 实用性
  • 易用性测试没有具体量化的指标,主观性较强。

7.5.4 兼容性测试

软件兼容性测试是指验证软件之间是否正确地交互和共享信息。

  • 硬件兼容
  • 软件之间兼容
  • 数据之间兼容
  • 向前和向后兼容:
    • 向后兼容是指可以使用软件的以前版本。
    • 向前兼容指的是可以使用软件的未来版本。

7.5.5 可安装性测试和可恢复性测试

7.5.5.1 可安装性测试

  • 系统软件安装
  • 应用软件安装
  • 服务器的安装
  • 客户端的安装
  • 产品升级安装
  • 等等

7.5.5.2 可恢复性测试

  • 恢复测试主要检查系统的容错能力。当系统出错时,能否在指定时间间隔内修正错误或重新启动系统。
  • 恢复测试首先要通过各种手段,让软件强制性地发生故障,然后验证系统是否能尽快恢复。

7.5.6 文档测试

  • 非代码的文档测试主要检查文档的正确性、完备性和可理解性。

7.6 软件缺陷的描述

7.6.1 基本的缺陷生命周期

image-20210526095141320

7.6.2 严重性和优先级

  • 严重性(severity)衡量缺陷对客户满意度的影响程度:致命的(fatal)、严重的(critical)、一般的(major)、微小的(minor)
  • 优先级(Priority):指缺陷被修复的紧急程度。立即解决P1、高优先级P2、正常排队P3、低优先级P4。

7.6.3 完整的缺陷信息

  • 前提
  • 操作步骤
  • 期望结果
  • 实际结果
  • 其他缺陷属性

文章作者: fdChen
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 fdChen !
评论
  目录
加载中...