建立缺陷预防的思想,通过统计抽样等方式不断改进测试,自动工具完全支持测试用例的运行,开展各种与测试有关的度量活动。
首要目的不是发现bug,而是确保被测系统满足需求。
测试不能丢给用户去做。
精确、完备、无冗余、简单、易于调试
1.定义需求(委托方提出)
2.分析需求(双方共同执行,生成需求规格说明)
3.实现需求(开发人员)
4.校验需求(测试人员)
1.人工化
2.自动化
1.动态测试
2.静态检查
(提供被测对象、准备相关预期、设计测试用例、搭建测试环境、运行测试用例、检查测试结果、记录测试过程、报告发现的缺陷、执行回归测试)
(提供被测对象、准备用户需求、阅读代码、阅读文档、报告发现的缺陷、执行回归测试)
(提供被测对象、准备用户需求、搭建测试环境、设计测试用例、编写测试脚本、运行测试用例、检查测试结果、记录测试过程、报告发现的缺陷、执行回归测试)
覆盖度高、数量少、冗余度低、缺陷定位能力高、复杂度低。
1.计划
(时间、计划人、使用方法、涉及资源、遵循标准、测试对象、可能的风险)
输入:需求规格说明、项目计划
输出:测试计划
2.设计
(设计测试样例、设计测试过程)
输入:需求、设计文档、测试计划
输出:测试用例、测试过程
3.实施
(运行测试用例、检查测试结果、提交测试报告)
输入:测试用例、测试过程、需求
输出:测试驱动模块、测试桩模块、(测试脚本)
4.评估
(评估测试系统、评估被测系统)
输入:测试用例、缺陷报告、测试标准
输出:测试评估报告
核心:抓住用户需求
措施:软件质量控制
纠编:测试人员不应对所有缺陷负责
需求模糊不清(需要需求规格说明)
需求变化无常(应确保需求稳定)
1.正常数据
2.错误数据
(满足数据类型但不在范围内、不完全满足数据类型、输入条件缺失)
3.边界数据
可以理解为从输入域到输出域的映射。
简单有效、开发与测试可以并行、对测试人员技术要求低。
1.寻找边界
2.定义邻域(每个邻域大小可不同)
3.选择测试数据
4.设计用例
1.划分等价类(即某段区域内数据性质相同)
可以将一段区域分为一个有效等价类(测试功能是否实现)与两个无效等价类(测试容错性)
2.设计测试用例
比如被两个条件划分成 n ∗ m n*m n∗m块等价类,只需要 m a x ( m , n ) max(m,n) max(m,n)个数据即可。
一般采用强覆盖,开发周期紧迫时用弱覆盖。
比如被两个条件划分成 n ∗ m n*m n∗m块等价类,需要 m n mn mn个。
缺陷:
1.可能会改变输入域(比如原输入域是由多个条件约束得到的,但用等价类测试可能会让输入域变为多个条件取并集)
2.对于无效等价类不需要等价类测试(???)
3.可能有漏洞和冗余(在多条件约束下,某些时候一些等价类可以被合并)
(???)
记 k k k为参数个数(互相独立),第 i i i个有 n i n_i ni种取值方法( n 0 ≥ n 1 ≥ n 2 ≥ . . . ≥ n k − 1 n_0\geq n_1 \geq n_2\geq ...\geq n_{k-1} n0≥n1≥n2≥...≥nk−1),两两组合需要 ∏ i = 0 k − 1 n i \prod_{i=0}^{k-1}n_i ∏i=0k−1ni。
定义正交表 L n ( q s ) L_{n}(q^{s}) Ln(qs),其中 n n n为测试用例数, q q q为取值个数, s s s为输入的条件数。(即每个条件的q一样,每个测试用例都需要s个条件)
当每个测试用例都需要s个条件,但q不同时,选取最大的作为q。
以 L 9 ( 3 4 ) L_{9}(3^4) L9(34)为例。其中每一个的范围都是1,2,3。
测试用例编号 | 输入条件1 | 输入条件2 | 输入条件3 | 输入条件4 |
---|---|---|---|---|
1 | 1 | 1 | 1 | 1 |
2 | 1 | 2 | 2 | 2 |
3 | 1 | 3 | 3 | 3 |
4 | 2 | 1 | 2 | 3 |
5 | 2 | 2 | 3 | 1 |
6 | 2 | 3 | 1 | 2 |
7 | 3 | 1 | 3 | 2 |
8 | 3 | 2 | 1 | 3 |
9 | 3 | 3 | 2 | 1 |
该表中每个条件的每个数据出现次数相同。
对于 m n mn mn类型的等水平正交表中,
n = 1 + s ∗ ( q − 1 ) n=1+s*(q-1) n=1+s∗(q−1)。
n ≥ ∑ i = 1 s ( q i − 1 ) n\geq\sum_{i=1}^{s}(q_i-1) n≥∑i=1s(qi−1)(最少需要的测试用例)
定义正交表 L n ( ∏ q i s i ) L_{n}(\prod q_{i}^{s_i}) Ln(∏qisi),其中 n n n为测试用例数, q q q为取值个数, s s s为输入的条件数。**
主要考虑成对覆盖率,即两两组合后,需要多少个测试样例才能完全覆盖所有等价域。
应该以最少的测试用例数目,覆盖尽可能多的成对组合元素。
eg:对于3个因素 A , B , C A,B,C A,B,C,各自有两种不同取法。
两两组合一共 2 3 = 8 2^3=8 23=8种情况
则对于第一组(A1,B1,C1),有(A1,B1),(A1,C1),(B1,C1)三种情况,覆盖了3种,故覆盖率为 3 8 = 37.5 % \frac{3}{8}=37.5\% 83=37.5%。
但如果加上一组(A2,B1,C1),则在原来基础上多了(A2,B1),(A2,C1)则,覆盖率变为 5 8 = 62.5 % \frac{5}{8}=62.5\% 85=62.5%
假设有 k k k个因素,每个因素有 q q q个取值。
那完全覆盖需要 q 2 q^2 q2个。
正交表满足100%成对组合覆盖
1.构造一个集合T,其包括所有条件的所有取值。
2.生成一条测试用例tc,并删除T中包含tc的。直到T为空。
每次生成一条测试用例tc时,在所有取值可能中,将出现最多的来作为tc的一个取值,其余的则随机排序。如此反复直到T为空。
1.先选择2个因素生成一组测试用例集合(即包含这两个因素的所有取值的两两组合)
2.水平方向上扩展(即加入一个因素),并从中选择一个新的取值,保证成对覆盖率尽量高。
3.如果水平方向仍然存在未被覆盖的成为组合,则在垂直方向上扩展。
通过同一事件的不同触发顺序与处理结果形成事件流。
通常是高风险事件流(操作频率高、设计规则复杂、功能重要、用户类型广泛、用户数量大、交互复杂等)
1.找到输入条件
2.判断是否是有效条件
3.判断是否触发了条件
4.需要取得的数据
5.得到预期输出
基本流 | 备选流 | |
---|---|---|
数量 | 1条 | 1条或多条 |
初始节点位置 | 系统初始状态 | 基本流或其他的备选流 |
终止节点位置 | 系统默认终止状态 | 基本流或者其他终止状态 |
是否为完整的业务流程 | 是 | 否、只是业务流程的片段 |
能否构成场景 | 能 | 否、需要和基本流共同构成场景 |
调用被测单元
运行测试用例
校验实际输出
判断测试结果(通过或失败)
如果发现bug,则记录缺陷
一次点击,运行所有
一次编写,重复测试
更少的编程
更简单的编程
灵活的测试
让脚本自动获取输入、校验、判断、记录缺陷
需要将测试代码从产品代码中分离出来
常用,JUnit3,JUnit4,JUnit5
对应包:org.junit.*
创建和执行测试用例
自动校验测试结果
测试的执行结果
组织和执行测试
与测试用例关联
自动校验执行结果
自动记录执行过程
支持测试用例的独立性
支持灵活的测试组织
支持自动统计
支持快速重复测试
支持测试的重用
支持测试代码的独立性
1.创建测试类
2.编写测试方法
2.1创建被测类对象 XXX.setParam(被测数据)
2.2调用被测方法
2.3利用断言执行校验 assertTrue(判断条件);
@Test:执行测试样例
@Before:在每个测试用例执行前执行一次
@After:在每个测试用例执行之后执行一次
@BeforeClass:在测试类的所有测试用例执行之前执行一次
@AfterClass:在测试类的所有测试用例执行之后执行一次
@Parameters(name="{测试编号}:函数名[参数]=函数")(输出格式)
@Parameterized.Parameter(编号) 定义测试的样例参数下标
1.制定参数化运行器
2.准备测试数据(构造器注入)
2.1定义参数:定义私有变量,用于保存输入样例。
2.2引入参数:定义带参数的构造方法
2.3准备测试数据:定义一个特殊方法
3.添加test方法,执行调试
1.制定参数化运行器
2.准备测试数据(属性注入)
2.1定义参数:定义公有变量,用于保存输入样例。
2.2引入参数:指定每个属性为参数
2.3准备测试数据:定义一个特殊方法
3.添加test方法,执行调试
@Parameters(name="{index}:function[{0},{1}…]={2}")
name为固定名称
function为测试用例序号
0,1,2表示参数的序号
选择类中部分测试用例,组织成新的测试集并执行
针对性强,便于快速定位缺陷。
在函数级别开始测试工作,缺陷修复的成本低。
有助于了解测试的覆盖程度。
有助于代码优化和缺陷预防。
门槛高,测试人员需要有一定的编程经验。
成本高,准备时间较长。
线性结构(无选择无循环)
条件判定结构(if&switch)
循环结构(while-do,do-while)
关注判定节点固有的复杂性(判定表达式、逻辑覆盖测试)
关注判定结构与循环结构对执行路径产生的影响(路径、独立路径测试)
关注循环结构本身的复杂性(循环体、基于数据的动态分析)
保证可执行语句(非判定节点)至少执行一次。
关注语句而并非判定节点(控制流的重点是判定节点),对隐式分支(因为结构本身错误,如判定点条件错误)无效。
保证每个判定节点能取到所有可能。
但判定节点为复合判定式子时,判定覆盖只关心其整体取值、因此无法覆盖到每个子条件的取值情况。
保证程序每个复合判定表达式中,每个简单判定条件(子条件)的取真和取假情况至少各执行一次。
条件覆盖不一定满足判定覆盖。
虽然深入检查了判定节点的每一个子条件,但不能保证整体的完全覆盖
保证判定节点的取真、取假至少各执行一次、每个简单判定条件的取真、取假也至少执行一次。
增加判定节点个数、增加子路径的数目、增加程序结构复杂度
保证每个判定节点中,所有简单判定条件(子条件)的所有可能取值组合至少执行一次
方法简单,但测试用例太多,冗余严重(即部分数据的路径相同,且如果子条件前后关联,路径还可能不存在 )。
在满足判定/条件覆盖的基础上,每个简单判定条件(子条件)都应该独立地影响到整个判定表达式的取值
1.列出所有简单判定条件(子条件)
2.列出真值表
3.对于每个简单判定条件,找到能够对整个判定结果产生独立影响的测试用例集合(独立音响对,可能不止一组)
与动态测试的区别:无需搭建环境、设计用例等,直接阅读文档与代码。
开发早期无法提供可运行对象,导致无法执行测试。
特定的缺陷无法通过测试发现。
促使参与者在有监督压力下工作,提高责任心
有助于开发早期发现需求和设计中的缺
有助于帮助程序员发现不足,提高工作质量
核心:缺陷预防
目的:发现缺陷,改进开发过程
方法:审查,团队评审,走查(多于2人,过程复杂,目的是发现缺陷、改进开发质量),结对编程,同行桌查,轮查,特别检查(1~2人,较随意,过程简洁,目的是发现缺陷)
结果:正常、延期、取消
1.计划评审会议(提前3天提交申请表)
(可选)2.召开评审预备会(提出申请,由主持人决定是否召开。)
确保参加的人员了解评审流程与目的,理解自己的责任,且评审员得到的资料正确无误。
3.准备评审会议:
4.召开正式评审会议
(可选)5.召开第三小时会议
6.修复缺陷
7.确认修复
入度越大,缺陷传播速度越快
出度越大,对缺陷敏感度越高
节点表示一条或多条语句???每种图案的功能
边表示节点之间的控制走向(语句执行)
直观反映函数的内部逻辑结构
展示程序中明显的缺陷
揭示程序是否隐含缺陷
1.V(G)=图中区域数
2.V(G)=边数-结点数+2
以上图为例,10-7+2=5。
3.V(G)=判定节点数(出度>1)+1
以上图为例,ABCD是判定节点,4+1=5。
1.结合源代码寻找独立路径
2.补充其他具有高风险的路径进行测试
为了避免场景爆炸(即场景数量太多,需要挑选出最重要、风险最高的典型场景来测试)
当事件流之间相互独立时,可以采用基于独立路径。
当事件之间存在关联时,先基于独立路径,再基于需求。
1.数量庞大,需要组织起来实现分级管理
2.测试用例是连接需求与缺陷的关键纽带
3.项目组人员众多,必须保证所有人正确理解测试用例
只有可以重现的缺陷,才有可能进行定位,以及修复。
无法重现的缺陷是无法修复的。(部分缺陷可能无法重现)
1.测试前进行相关环境与数据备份
2.详细记录每一个测试步骤与系统响应
3.使用不同的测试数据或操作步骤,或改变测试环境,看能否触发缺陷。
4.重复相同测试,至少3次
1.基本信息(被测对象、负责人、测试用例)
2.核心信息(测试条件、操作、缺陷内容、基本属性)
3.缺陷类型
指定缺陷处理优先级和分配缺陷处理负责人
解决方案,描述修复详情。
缺陷是否正确修复。
1.及时报告。
2.一个缺陷对应一个缺陷报告。
3.对缺陷描述更紧凑,确切,充分,避免错误。
4.在缺陷周边进行更多测试。
针对系统功能需求展开测试,确认被测系统是否满足用户功能使用要求。
用例设计、系统输入、系统内部处理、系统输出
1.可以快速得到可回放的测试比较结果
2.自动生成可直接使用的测试脚本
3.自动准备测试数据
4.回归测试中可准确重复执行指定测试用例
1.表现层(web服务器)
2.业务逻辑层(应用服务器)
3.数据层(数据库服务器)
硬件:服务器、客户端、交换机
软件:数据库、中间件、被测系统、操作系统
网络:有线/无线/宽带、网络协议
1.硬件环境:服务器环境、网络环境
2.软件环境:版本一致性,场景一致性
1.性能测试计划
2.性能测试需求分析
3.性能测试用例的编写
4.性能测试用例执行
5.性能测试分析
6.性能测试报告
反映软件满足明确或隐含需要能力的特性总和
根据经验,使用典型的质量因素来构建多层质量模型。
用户不了解软件内部实现细节,但用户了解自己的需求。
从 外部视角(外部可观察到的特性,黑盒) 定义与描述软件
开发人员从内部视角**(从内部可以观察到的特性,白盒)**构建软件属性
可维护性(软件系统可修复、改进的难易程度要求)
简单性
简洁性
自描述性
模块性
灵活性(修改或改进一个已投入运行的软件所需工作量的大小)
可扩展性
通用性
自描述性
可测试性(测试软件所需工作量的大小)
可维护性
灵活性
可测试性
简单性
工具性
自描述性
模块性
可移植性(移植软件系统所需工具量大小)
机器独立性
软件系统独立性
自描述性
可重用性
通用性
模块性
机器独立性
软件系统独立性
自描述性
可互操作性
模块性
通信通用性
数据通用性
正确性(软件满足规格说明与用户预期目标)
可追溯性(对软件开发历史、软件发布后的情况进行跟踪的能力)
完备性
一致性
完整性
访问控制(根据用户身份限制功能)
访问审查
可靠性
精度
容错性(防止由于外部接口错误导致系统失效???)
一致性
效率
运行效率(运行平台、系统架构)
存储效率
可用性(易学、高效、好记、少错、满意度)
可操作性
训练性
通信性
外部度量:在测试和使用软件时测量系统行为
内部度量:在软件设计和编码时分析产品
通过提供一些方法来构建一个质量模型,包括质量属性之间关系的构建和对质量属性进行分析
Who(谁),When(何时),What(调查什么),How(怎么查),结论如何
审查规范化
审查目标保持明确
保证审查进度
作为审查记录存档
减少审查人员偏见与随意性
帕累托图:寻找影响质量因素中关键的少数,以便优先解决主要问题???
直方图:观察数据分布规律,判断总体质量分布
有利于观察变量之间的数量关联趋势
观察是否存在偏离大多数点的离群值
由**问题(标在骨头外)与产生原因(在鱼骨上长出鱼刺)**组成
DrGilbert 2020.3.20