软件质量保证与测试技术
软件质量保证过程
软件质量与缺陷
软件质量定义
IEEE: 质量是系统、部件或过程满足
- 明确需求
- 客户或用户需要或期望的程度
软件质量 (GB/T 11457-2006):
- 软件产品满足用户要求的程度;
- 软件具有所期望的各种属性的组合程度;
- 软件满足用户综合期望的程度;
- 软件在使用中满足用户要求的程度。
软件质量评估
软件质量是人们实践产物的属性和行为,是可以认识以及科学描述的,并且可以通过一些方法和人类活动来改进的。
软件质量模型:McCall模型、Boehm模型、ISO 9126模型
McCall软件质量模型(1977)
Boehm软件质量模型(1978)
三层模型:
- 质量要素(7个)
- 衡量指标(15个)
- 度量指标
ISO 9126软件质量模型(1993)
三层模型:
- 外部质量特性(6个)
- 内部质量子特性(27个)
- 用户自定义的度量指标
软件缺陷
定义:任何程序、系统中的问题,和产品设计书的不一致性,不能满足用户的需求
现象:
- 功能、特性没有实现或部分实现
- 设计不合理,存在缺陷
- 实际结果和预期结果不一致
- 运行出错,包括运行中断、系统崩溃、界面混乱
- 数据结果不正确、精度不够
- 用户不能接受的其他问题,如存取时间过长、界面不美观
产生:
- 技术问题:算法错误,语法错误,计算和精度问题,接口参数传递不匹配;
- 团队工作:沟通不充分,误解;
- 软件本身:
- 文档错误、用户使用场合(user scenario)不正确;
- 时间上不协调、或不一致性所带来的问题;
- 系统的自我恢复或数据的异地备份、灾难性恢复等问题;
构成:
在不同阶段的分布
在真正的程序测试之前,通过审查、评审会可以发现更多的缺陷。
规格说明书的缺陷会在需求分析审查、设计、编码、测试等过程中会逐步发现,而不能在需求分析一个阶段发现。
修复缺陷成本:
软件测试和开发、质量保证的关系,TDD
软件测试与开发的关系
软件质量保证(SQA)
软件质量保证(Software Quality Assurance,SQA)活动是通过对软件产品有计划的进行评审和审计来验证软件是否合乎标准的系统工程,通过协调、审查和跟踪以获取有用信息,形成分析结果以指导软件过程。
-
对软件工程各个阶段的进展、完成质量及出现的问题进行评审、跟踪。
-
审查和验证软件产品是否遵守适用的标准、规程和要求,并最终确保符合标准、满足要求。
-
建立软件质量要素的度量机制,了解各种指标的量化信息,向管理者提供可视信息。
测试 vs. SQA
SQA指导、监督软件测试的计划和执行,督促测试工作的结果客观、准确和有效,并协助测试流程的改进。
软件测试是SQA重要手段之一,为SQA提供所需的数据,作为质量评价的客观依据。
SQA是一项管理工作,侧重于对流程的评审和监控
测试是一项技术性的工作,侧重对产品进行评估和验证
测试驱动开发(TDD)的思想
- 明确当前要完成的功能。可以记录成一个 TODO 列表。
- 快速完成针对此功能的测试用例编写。
- 测试代码编译不通过。
- 编写对应的功能代码。
- 测试通过。
- 对代码进行重构,并保证测试通过。
- 循环完成所有功能的开发。
软件测试分类
不同的分类:
- 按测试的对象或范围分类,如单元测试、文档测试、系统测试等
- 按测试目的分类,如功能测试、回归测试、性能测试、可靠性测试、安全性测试和兼容性测试等
- 根据测试过程中被测软件是否被执行,分为静态测试和动态测试
- 根据是否针对系统的内部结构和具体实现算法来完成测试,可分为白盒测试和黑盒测试
静态和动态测试
静态测试:轮查、互审、走读、审查会议(非正式到正式)
动态测试:运行程序
- 将需求和设计的评审纳入测试的范畴,可看作是广义测试
- 静态测试包括对软件产品的需求和设计规格说明书的评审、对程序代码的复审等
- 静态分析的查错和分析功能是其他方法所不能替代的,可以采用人工检测和计算机辅助静态分析手段进行检测,但越来越多地采用工具进行自动化分析
- 动态测试是通过真正运行程序发现错误,通过观察代码运行过程,来获取系统信息,对系统行为进行验证。
黑盒测试与白盒测试
黑盒测试:
白盒测试
小结
软件测试级别及任务
系统功能性测试
功能测试一般须在完成集成测试后进行,而且是针对应用系统进行测试。功能测试是基于产品功能说明书,是在已知产品所应具有的功能,从用户角度来进行功能验证,以确认每个功能是否都能正常使用 。
系统非功能性测试
系统非功能性测试是将软件放在整个计算机环境下,包括软硬件平台、某些支持软件、数据和人员等,在实际运行环境下进行一系列的测试,包括:
- 恢复测试
- 安全测试
- 强度测试
- 性能测试
主动测试和被动测试
主动测试方法:测试人员主动向被测试对象发送请求、或借助数据、事件驱动被测试对象的行为,从而验证被测试对象的反应或输出结果。
被动测试方法:测试人员不干预产品的运行,而是被动地监控产品在实际环境中运行,通过一定的被动机制来获得系统运行的数据,包括输入、输出数据。
α、β测试
Alpha testing is simulated or actual operational testing by potential users/customers or an independent test team at the developers‘ site;Is a form of internal acceptance testing.
Beta testing comes after Alpha testing. Versions of the software, known as beta versions, are released to a limited users outside of the programming team.
静态测试
代码审查﹑走查等的概念及区别
定义:对组件/系统进行规格或实现级别的测试,而不是执行这个软件,比如代码评审。
代码检查主要检查代码和设计的一致性,代码对标准的遵循、可读性、代码逻辑表达的正确性及代码结构的合理性等方面,包括以下两种形式:
- 代码审查和走查由若干程序员与测试员组成一个小组,集体阅读并讨论程序,或者用“脑”执行并检查程序的过程。(头脑风暴会)
- 桌面检查是由程序员阅读自己所编写的程序。
代码审查
-
以组为单位阅读代码,是一系列规程和错误检查技术的集合。
-
代码审查小组
- 4人组成,1人为调协人
- 协调人应该是个称职的程序员,但不是该程序的编码人员,不需要对程序的细节了解得很清楚
- 协调人的职责:
- 为代码审查分发材料、安排进程
- 在代码审查中起主导作用
- 记录发现的所有错误
- 确保所有错误随后得到改正
- 第二个小组成员是代码的作者,其它成员通常是程序的设计人员以及一名测试专家。该测试专家应具备较高的软件测试造诣并熟悉大部分的常见错误。
-
审查议程与注意事项
- 在审查前几天,协调人将程序清单和设计规范分发给其他成员。所有成员应在审查之前熟悉这些材料。在审查进行时,主要进行两项活动:
- 由程序编码人员逐条语句讲述程序的逻辑结构,小组其它成员应提问题、判断是否存在错误。
- 参考常见的编码错误列表分析程序
- 协调人负责确保审查会议的讨论高效地进行、每个参与者都将注意力集中于查找错误而不是修正错误(错误的修正由程序员在检查会议后完成)
- 代码审查会议的理想时间应在90-120分钟。
- 开会是一项繁重的脑力劳动,会议时间越长效率越低。大多数的代码审查都是按每小时大约阅读150行代码的速度进行。因此,对大型软件的审查应安排多个代码审查会议同时进行,每个代码审查会议处理一个或几个模块或子程序。
- 对事不对人,和人有关的注意事项
- 审查是发现程序的错误,从而改进软件质量。
- 在审查前几天,协调人将程序清单和设计规范分发给其他成员。所有成员应在审查之前熟悉这些材料。在审查进行时,主要进行两项活动:
错误类型
-
数据引用错误
-
变量使用前是否赋值或初始化?
- 容易引起变量使用错误,特别是对于指针或引用变量。
- 在java中要求变量在使用前必须初始化。
-
数组下标的范围和类型
- 是否存在下标越界错误,下标类型是否为整型。
-
通过指针引用的内存单元是否存在(虚调用)?
- 如在函数返回局部变量的指针或引用时会产生虚调用错误。
-
被引用的变量或内存的属性是否与编译器预期的一致?
- 如A类型的指针或引用是否指向的是非A类型对象。
-
-
数据声明错误
- 是否所有变量都已声明?
- 绝大多数编程语言要求变量先定义后使用,可保证变量使用的安全性。
- 默认的属性(默认值)是否正确?
- 变量的初始化是否正确?变量的初始化是否与其存储空间的类型一致?
- 是否每个变量都有正确的长度、类型和存储类别?
- 是否存在相似名称的变量?
- 是否所有变量都已声明?
-
运算错误
- 是否存在非算术变量之间的运算?
- 是否存在混合模式的运算?( int与float类型)
- 是否存在不同字长变量之间的运算?(int与long类型)
- 目标变量大小是否小于所赋值的大小?(精度损失或越界错误)
- 中间结果是否上溢或下溢?
- 是否存在除0错误?
- 操作符的优先顺序是否正确?
- 整数除法是否正确?(精度问题,如2*(i/2)==i)
-
比较错误
- 是否有不同类型数据的比较运算?(如日期与数字)
- 是否有混合模式或不同长度数据的比较运算?
- 比较运算符是否正确?(如至多、至少,不小于)
- 布尔表达式(与、或、非)是否正确?
- 比较运算符是否与布尔表达式相混合?(如2<i<10对吗?)
- 是否存在浮点数的比较?
- 优先顺序是否正确?(例如if((a==2) && (b==2) || (c==3))
- 布尔表达式的计算方式(例如 if((x==0 && (y/x)>z))
-
控制流程错误
- 是否所有循环都能终止?(循环结束条件是否能满足以及递归的终止条件是否能满足。)
- 是否存在由于入口条件不满足而跳过循环体?(do…while循环)
- 是否存在仅差一个的循环错误?(如for(int i=0;i<=10;i++){})
- 程序结构中括号是否匹配、if…else是否匹配、do…while是否匹配、try…catch是否匹配等。
-
接口错误
- 形参和实参的数量是否相等?
- 形参的属性是否与实参的属性相匹配?
- 形参的属性是否与实参的顺序相匹配?
- 形参的单位是否和实参匹配?(属逻辑错误)
- 是否改变了某个仅作为输入值的形参?(C++中的const关键字)
- 全局变量的定义是否一致?
-
输入输出错误
- 文件属性是否正确?
- 打开文件的语句是否正确?
- 缓冲区、内存大小是否足够来保留程序将读取的文件?
- 文件在使用前是否打开?
- 文件在使用后是否关闭了?
- 文件结束条件是否被正确处理?
- 是否处理了IO错误?
- 打印或输出的文本信息中是否存在拼写或语法错误?即输出结果正确性。
-
其他检查
- 是否存在未引用过的变量?
- 编译通过的程序是否存在“警告”或“提示”信息?
- 程序或模块是否对输入的合法性进行了检查?是否考虑到所有的场景?(如第一章中三角形例)
- 程序是否遗漏了某个功能?
代码走查
走查与代码审查大体相同,以小组为单位进行代码阅读,但是规程稍微不同,采用的错误检查技术也不一样。
- 走查的参与者“使用了计算机”;
- 被指定为测试人员的那个人会带来一些书面的测试用例来参加会议;
- 会议期间,每个测试用例都在人们脑中进行推演,程序的状态(如变量的值)记录在纸张或白板上以供监视。
- 这些测试用例必须结构简单、数量较少,因为人脑执行程序的速度比计算机执行速度慢若干数量级。因此,这些测试用例本身并不起到关键的作用;相反,它们的作用是提供了启动代码走查和质疑程序员逻辑思路及其设想的手段。
- 在大多数的代码走查中,很多问题是向程序员提问的过程中发现的,而不是测试用例本身直接发现的。
重点---动态测试(测试用例设计)
要掌握用例设计的步骤,并会灵活应用到具体问题上。
黑盒
等价类划分、边界值分析、决策表、因果图
等价类划分法
等价类是某个输入域的子集,在该子集中每个输入数据的作用是等效的。将输入数据分成若干个子集,从每个子集选取一个代表性的数据作为测试用例。
- 分为有效等价类和无效等价类。
- 在分析需求规格说明的基础上划分等价类,列出等价类表
设计测试用例时,要同时考虑这两种等价类。因为软件不仅要能接收合理的数据,也要能经受异常数据的考验。经过正反的测试才能确保软件具有更高的可靠性。
确定等价类的方法
在输入条件规定了取值范围或值的个数的情况下,则可以确立一个有效等价类和两个无效等价类
在输入条件规定了输入值的集合或者规定了“必须如何”的条件的情况下,可以确立一个有效等价类和一个无效等价类。
在输入条件是一个布尔量的情况下,可确定一个有效等价类和一个无效等价类。
在规定了输入数据的一组值(假定n个),并且程序要对每一个输入值分别处理的情况下,可确立n个有效等价类和一个无效等价类。
- 交通工具的类型必须是公共汽车、卡车、出租车、火车或摩托车
在规定了输入数据必须遵守的规则的情况下,可确立一个有效等价类(符合规则)和若干个无效等价类(从不同角度违反规则)。
- 页面上用户输入有效E-mail地址的规则
根据等价类创建测试用例的步骤
-
建立等价类表,列出所有划分出的等价类
输入条件 有效等价类 无效等价类 … … … … … … -
为每个等价类规定一个唯一的编号
-
设计一个新的测试用例,使其尽可能多地覆盖尚未覆盖的有效等价类
-
重复3,最后使得所有有效等价类均被测试用例所覆盖
-
设计一个新的测试用例,使其只覆盖一个无效等价类
-
重复5使所有无效等价类均被覆盖
用单个测试用例覆盖无效等价类,是因为某些特定的输入错误检查可能会屏蔽或取代其他输入错误检查。例如,若规定了“请输入书籍类型(硬皮、软皮或活页)及数量(1-999)”,代表两个错误输入(书籍类型错误,数量错误)的测试用例“XYZ 0”,很可能不会执行对数量的检查,因为程序会提示“XYZ是未知的书籍类型”,就不检查输入的其余部分了。
示例
有一报表处理系统,要求用户输入处理报表的日期。假设日期限制在2000年1月至2020年12月,即系统只能对该段时期内的报表进行处理。若用户输入的日期不在这个范围内,则显示错误信息。并且此系统规定日期由年月的6位数字组成,前4位代表年,后两位代表月。则检查日期时,有哪些等价类?
测试用例:覆盖1、5、8三个有效等价类测试,只要用201006即可;对无效等价类的测试要分别输入7个非法数据,如200a0b、20102、1012012、198802、203011、200000、202013
边界值分析法
- 很多错误发生在输入或输出范围的边界上,因此针对各种边界情况设置测试用例,可以更有效地发现缺陷。
- BVA – Boundary Value Analysis
- 设计方法
- 确定边界情况(输入或输出等价类的边界)
- 选取正好等于、刚刚大于或小于边界值作为测试数据
确定边界值的方法
如果输入条件规定了值的范围,则应取刚达到这个范围的边界的值,以及刚刚超越这个范围边界的值作为测试输入数据。
如果输入条件规定了值的个数,则用最大个数、最小个数、比最小个数少一、比最大个数多一的数作为测试数据。
如果程序的规格说明给出的输入域或输出域是有序集合,则应选取集合的第一个元素和最后一个元素作为测试用例(例如:图片像素)。
如果程序中使用了一个内部数据结构,则应当选择这个内部数据结构的边界上的值作为测试用例。
示例一
Test cases for ABS(x) :
class x < 0, arbitrary value: x = -10
class x >= 0, arbitrary value x = 100
classes x < 0, x >= 0, on boundary : x = 0
classes x < 0, x >= 0, below and above: x = -1, x = 1
示例二
测试限制性用户输入:6位正整数
示例三
Test cases :
- 任意的正常值:随机选择几个选项
- 边界值:选择所有选项
- 边界值:一个都不选
- 边界值:选择一个选项
数值边界值检验
计算机基于二进制工作,软件任何运算都有一定的范围限制。
0 和 1, byte 由8 bits 构成, 字由4 bytes构成, …
字符的边界值检验
ASCII是常见的编码方式
示例四:
一个二元函数f(x, y)
-
1=<x<=12
-
1=<y<=31
-
(1, 15), (0, 15), (2, 15), (12, 15), (11, 15), (13, 15)
-
(6, 15)
-
(6, 1), (6, 0) , (6, 2) , (6, 31) , (6, 30) , (6, 32)
示例五:
假设商店货品价格(R) 都不大于100元(且为整数),若顾客付款(P)在100元内,现有一个程序能在每位顾客付款后给出找零钱的最佳组合(找给顾客货币张数最少)。
假定此商店的货币面值只包括:50元(N50)、10元(N10)、 5元(N5)、1元(N1) 四种。
基于组合及其优化的技术
判定表方法
在实际应用中,许多输入是由多个因素构成,而不是单一因素,这时就需要多因素组合分析。
对于多因素,有时可以直接对输入条件进行组合设计,不需要进行因果分析,即直接采用判定表方法。
判定表由“条件和活动”两部分组成,即列出一个测试活动执行所需的条件组合,所有可能的条件组合定义了一系列的选择,而测试活动需要考虑每一个选择。
判定表有时也称“决策表”。
“阅读指南”决策表
判定表元素
条件桩:列出问题的所有条件
动作桩:列出可能针对问题所采取的操作
条件项:针对所列条件的具体赋值
动作项:列出在条件项(各种取值)组合情况下应该采取的动作。
规则:任何一个条件组合的特定取值及其相应要执行的操作。
判定表方法步骤
- 列出条件桩
- 列出动作桩
- 填入条件项及其组合
- 填入动作项,制定初始判定表;
- 简化、合并相似规则或者相同动作
示例
问题要求:”……对功率大于50马力的机器,当维修记录不全或已运行10年以上时,应给予优先的维修处理;对功率小于50马力的机器,当运行超过10年时也优先维修……” 。这里假定,“维修记录不全”和“优先维修处理”均已在别处有更严格的定义 。请建立判定表。
解答:
① 确定规则的个数。这里有3个条件,每个条件有两个取值,故应有2*2*2=8种规则。
② 列出所有的条件桩和动作桩。
③ 填入条件项(二进制的真值表)。
④ 填入动作项。
⑤ 化简。
化简原则:
- 删除不存在的规则;
- 合并相似规则;
- 动作相同
- 该条件项包含所有取值(说明动作与该条件的取值无关)
总结
- 决策表(判定表)是分析和表达多逻辑条件下执行不同操作的情况的工具。
- 在一些数据处理问题当中,某些操作的实施依赖于多个逻辑条件的组合,即:针对不同逻辑条件的组合值,分别执行不同的操作。决策表很适合于处理这类问题。
- 基于决策表的测试是所有黑盒测试方法中最为严格、且最具逻辑性的测试方法。
- 优点:能够将复杂的问题按照各种可能的情况全部列举出来,简明并避免遗漏。因此,利用决策表能够设计出完整的测试用例集合。
- 缺点:不能表达重复执行的动作,例如循环结构
练习
假设中国某航空公司规定:
- 中国去欧美的国外航线都有食物供应,每个座位都可以播放电影。
- 中国去非欧美的国外航线都有食物供应,只有商务仓可以播放电影。
- 中国国内航班的商务仓有食物供应,但是不可以播放电影。
- 中国国内航班的经济仓只有当飞行时间大于2小时才有食物供应,但是不可以播放电影。
因果图法
-
多种输入条件的组合,产生多种结果设计测试用例。
-
产生背景:
- 等价类划分法和边界值分析方法都是着重考虑输入条件,但没有考虑输入条件的各种组合;
- 判定表方法考虑条件组合,但是没有考虑输入条件之间的相互制约关系;
- 如果在测试时必须考虑输入条件的各种组合,则可能的组合数目将是天文数字。
示例
基本符号
恒等-关系:果 j 取决于因 i。因出现,则果也出现。
非-关系:只有当因 i 不存在时,果 j 才出现。
或-关系:如果因 i1 或因 i2 或……或因 in 存在时,结果 j 才出现。
与-关系:只有当因 i1 与因 i2 与……与因 in 同时存在时,结果 j 才出现。
约束
-
输入状态之间可能存在某些依赖关系。
-
输出状态之间也往往存在约束。
-
在因果图中,用特定的符号标明这些约束。
-
输入条件的约束有以下4类:
-
E约束(异):a和b中至多有一个可能为1,即a和b不能同时为1。
-
I约束(或):a、b和c中至少有一个必须是1,即 a、b 和c不能同时为0。
-
O约束(唯一):a和b必须有一个,且仅有1个为1。
-
R约束(要求):a是1时,b必须是1,即不可能a是1时b是0。
-
-
输出条件约束类型
-
输出条件的约束只有M约束(强制):若结果a是1,则结果b强制为0。
-
设计方法
- 分析软件规格说明文档描述的哪些是原因(输入条件),哪些是结果(输出条件),给每个原因和结果赋予一个标示符;
- 找出原因与结果,原因与原因之间的对应关系,画出因果图;
- 在因果图上标上哪些不可能发生的因果关系,表明约束或限制条件;
- 根据因果图,创建判定表,将复杂的逻辑关系和多种条件组合很具体明确的表示出来;
- 把判定表的每一列作为依据设计测试用例。
示例
某软件规格说明书包含这样的要求:
- 第一列字符必须是A或B,第二列字符必须是一个数字,满足要求时进行文件的修改;
- 如果第一列字符不正确,给出信息L;
- 如果第二列字符不是数字,给出信息M。
- 根据题意,原因和结果如下:
原因:
1——第一列字符是A;
2——第一列字符是B;
3——第二列字符是一数字。
结果:
21——修改文件;
22——给出信息L;
23——给出信息M。
- 其对应的因果图如下:
11为中间节点;考虑到原因1和原因2不可能同时为1,因此在因果图上施加E约束。
表中8种情况的左面两列情况中,原因①和原因②同时为1,这是不可能出现的,故应排除这两种情况。表的最下一栏给出了6种情况的测试用例,这是我们所需要的数据。
示例
有一个处理单价为5角钱的饮料的自动售货机软件测试用例的设计。其规格说明如下:
假设只能投入5角钱或1元钱:
- 当投入5角钱,并押下〖橙汁〗或〖啤酒〗的按钮,则送出相应饮料;
- 当投入1元钱:
- 若售货机没有零钱找,则一个显示〖零钱找完〗的红灯亮,这时在投入1元硬币并押下按钮后,饮料不送出来而且1元硬币也退出来;
- 若有零钱找,则显示〖零钱找完〗的红灯灭,在送出相应饮料的同时找还5角硬币。
-
分析这一段说明,列出原因和结果
原因:
- 售货机有零钱找 /没零钱找(1或0)
- 投入1元硬币
- 投入5角硬币
- 押下橙汁按钮
- 押下啤酒按钮
结果:
-
售货机〖零钱找完〗灯亮 /灭(1或0)
-
退还1元硬币
-
退还5角硬币
-
送出橙汁饮料
-
送出啤酒饮料
-
画出因果图,如图所示。所有原因结点列在左边,所有结果结点列在右边。建立中间结点,表示处理的中间状态。中间结点:
-
投入1元硬币且押下饮料按钮
-
押下〖橙汁〗或〖啤酒〗的按钮
-
应当找5角零钱并且售货机有零钱找
-
钱已付清
-
-
转换成判定表
-
在判定表中,阴影部分表示因违反约束条件的不可能出现的情况,删去。第16列与第32列因什么动作也没做,也删去。最后可根据剩下的16列作为确定测试用例的依据
正交实验法
在许多应用系统的测试工作中,不会象判断三角形那样简单,输入条件的因素很多,而且每个因素也不能简单用“是”和“否”来回答。比如,微软Powerpoint程序的打印测试,也需要考虑4个因素,每个因素也有多个选项
- 打印范围分:全部、当前幻灯片、给定范围
- 打印内容分:幻灯片、讲义、备注页、大纲视图
- 打印颜色/灰度分: 彩色、灰度、黑白
- 打印效果分:幻灯片加框和幻灯片不加框。
测试组合会变得很多,如果按照传统的测试方法,会导致很大的测试工作量
依据Galois理论,从大量的(实验)数据(测试例)中挑选适量的、有代表性的点(条件组合),从而合理地安排实验(测试)的一种科学实验设计方法
产生背景
- 大部分缺陷是在两个变量取值冲突的测试时被发现的;
- 不仅仅是在所有的组合情况下才会发现所有的测试缺陷;
测试原理
- 不要测试所有的组合,测试所有的“Pairwise ”即可;
输入条件 | 完全组合数 | 两两组合数 |
---|---|---|
4个变量每个可取3种值 | \(3^4=81\) | 9 |
13个变量每个可取3种值 | \(3^{13}=1594323\) | 15 |
20个变量每个可取10种值 | \(10^{20}\) | 180 |
示例
系统S有三个输入变量X、Y、Z,其值域分别为:D(X) = {1, 2},D(Y) = {Q, R},D(Z) = {5, 6}.
第一步:列出所有可能的测试用例.
第二步:去掉重复的行。
方法如下:从表的最后一行开始,如果这行的两两组合值能够在上面的行或此表中找到,那么这行就可从用例集中删除。
TestID | Input X | Input Y | Input Z |
---|---|---|---|
TC1 | 1 | Q | 5 |
TC4 | 1 | R | 6 |
TC6 | 2 | Q | 6 |
TC7 | 2 | R | 5 |
白盒
语句﹑判定﹑条件﹑逻辑等
逻辑覆盖
以程序或系统的内部逻辑结构为基础,分为语句覆盖、判定覆盖、条件覆盖、判定-条件覆盖、条件组合覆盖等。
路径覆盖
在程序或业务控制流程的基础上,分析控制构造的环路复杂性,导出基本可执行路径集合,从而设计测试用例。
语句覆盖
基本思想
设计若干测试用例,运行被测程序,使程序中的每个可执行语句至少被执行一次:
- 如果是顺序结构,就只需让测试从头执行到尾;
- 如果有分支、条件和循环,则需要采用特定的一些方法,执行足够的测试覆盖全部语句。
判定覆盖
基本思想
- 设计若干用例,运行被测程序,使得程序中每个判断的取真分支和取假分支至少经历一次,即判断真假值均曾被满足。
一个判定代表着程序的一个分支,所以判定覆盖也被称为分支覆盖。
条件覆盖
判定覆盖是一种比语句覆盖更强的准则,但仍然相当不足。
E.g., 若第二个判断存在错误(如把a>1写成了a!=0),那么前面的两个测试用例是无法发现这个错误的。
条件覆盖的基本思想:
设计若干测试用例,执行被测程序以后,要使每个判断中每个条件的可能取值至少满足一次。
列出所有条件
覆盖所有条件
(a, b ,c)= (2, -1, 0) T1, F2, T3, F4
(a, b ,c)= (-1, 1, 2) F1, T2, F3, T4
条件覆盖不一定比语句覆盖、判定覆盖好!
两个测试用例在两个判断处都是F->T,即判定覆盖没有满足。进而语句覆盖也没有被满足。
判定-条件覆盖
判定-条件覆盖是判定和条件覆盖设计方法的交集,即设计足够的测试用例,使得判断条件中的所有条件可能取值至少执行一次,同时,所有判断的可能结果至少执行一次。
特定的条件会屏蔽其他的条件,常常并不能全部都执行到。
源程序中的多重条件判断被分解成单个的判断和分支。
大多数机器都没有执行多重条件判断的单独指令。
更为完全的测试覆盖似乎是将每个基本判断的全部可能的结果都执行到。
图示例子中X>1条件对应的决断结果可能不会被测试到。
条件组合测试
条件组合覆盖的基本思想
设计足够的测试用例,使得判断中每个条件的所有可能组合值至少出现一次,并且每个判断本身的判定结果也至少出现一次。
与条件覆盖的区别
它不是简单地要求每个条件都出现“真”与“假”两种结果,而是要求让这些结果的所有可能组合都至少出现一次。
示例:
覆盖了所有组合,但只覆盖了两条路径: 125, 134
覆盖了所有组合,但覆盖路径有限,1-2-5 没被覆盖
基本路径覆盖
顾名思义,路径覆盖就是设计所有的测试用例,来覆盖程序中的所有可能的执行路径。
路径覆盖实际考虑了程序中各种判定结果的所有可能组合,但并未考虑判定中的条件结果的组合。因此,虽然说路径覆盖是一种非常强的覆盖,但不能代替条件覆盖和条件组合覆盖。
实际软件系统中,即使一个不太复杂的程序,其路径组合都可能是一个庞大的天文数字,要想在测试中覆盖所有的路径往往不太现实。
- 如一个函数包含10个if语句,就有\(2^{10}=1024\)条路径测试,若再增加一个if语句,就有\(2^{11}=2048\)条路径要测试!!
- 必须把覆盖的路径数目减少到一定程度内!
- 因此有了“基路径测试法”
基路径覆盖的设计过程
- 依据代码绘制流程图
- 确定流程图的圈复杂度(cyclomatic complexity )
- 确定线性独立路径的基本集合( basis set )
- 设计测试用例覆盖每条基本路径
流程图的圈复杂度
圈复杂度(Cyclomatic complexity):也叫环路复杂度,代码逻辑复杂度的度量,提供了被测代码的路径数量。复杂度越高,出错的概率越大。
- V(G) = 区域数量(由节点、连线包围的区域,包括图形外部区域)
- V(G) = 连线数量 - 节点数量 + 2
- V(G) = 简单可预测节点数量(即流程图中判定节点的数量) + 1
示例
确定线性独立的路径集合
独立路径: 至少引入一个新的处理语句或条件的任何路径。V(G)值正好等于该程序的独立路径的条数。
基本集: 由独立路径构成的集合,每条路径是唯一的。由基本集导出的测试用例,保证每行代码语句至少被执行一次。
基本集合不一定唯一
示例
基本路径测试并不是测试所有路径的组合,仅仅保证每条基本路径被执行一次
小结
Myers给出了各种测试方法的综合策略:
- 在任何情况下都必须使用边界值方法。经验表明,用边界值分析法设计的测试用例发现错误的能力最强。
- 必要时使用等价类划分法补充一些测试用例。
- 根据经验或直觉推测程序中有可能存在的各种错误,用错误推测法追加一些测试用例。
- 分析已设计的测试用例的逻辑覆盖程度,若没有达到覆盖标准,再补充足够的测试用例。
- 如果规格说明中含有输入条件的组合情况,则可采用因果图法和决策表法。
集成测试
自顶向下﹑自底向上等集成策略
集成测试的模式
渐增式测试模式与非渐增式测试模式
非渐增式测试模式:先分别测试每个模块,再把所有模块按设计要求放在一起结合成所要的程序,如大棒模式。
渐增式测试模式:把下一个要测试的模块同已经测试好的模块结合起来进行测试,测试完以后再把下一个应该测试的模块结合进来测试。
驱动模块和桩模块概念和区别
驱动模块:用于模拟被测试模块的上一级模块,相当于被测试模块的主程序,用于接收测试数据,并把这些数据传送给被测试模块,启动被测试模块,最后输出实测结果。
桩模块:用于模拟被测试模块工作过程中所调用的模块。桩模块一般只进行很少的数据处理,不需要把子模块的所有功能都带进来,但不允许什么事情也不做。
示例
假设现在项目组把任务分给了7个人,每个人负责实现一个模块。你负责的是B模块,你很优秀,第一个完成了编码工作,现在需要开展单元测试工作。那么要怎么做呢?
做法:
- 写两个模块Sd和Se分别代替D模块和E模块(函数名、返回值、传递的参数相同),这样B模块就可以通过编译了。Sd模块和Se模块就是桩模块。
- 写一个模块Da用来代替A模块,里面包含main函数,可以在main函数中调用B模块,让B模块运行起来。Da模块就是驱动模块。
大棒集成方法(Big-bang Integration)
采用大棒集成方法,先是对每一个子模块进行测试(单元测试阶段),然后将所有模块一次性的全部集成起来进行集成测试 。
因为所有的模块一次集成的,所以很难确定出错的真正位置、所在的模块、错误的原因。这种方法并不推荐在任何系统中使用,适合在规模较小的应用系统中使用。
自顶向下法(Top-down Integration)
自底向上法 Bottom-up Integration
自顶向下VS自底向上
混合策略(Modified Top-down Integration)
混合法:
- 对软件结构中较上层,使用的是“自顶向下”法
- 对软件结构中较下层,使用的是“自底向上”法
三明治集成方法(Sandwich Integration)
优点:它将自顶向下和自底向上的集成方法有机地结合起来,不需要写桩程序,因为在测试初自底向上集成已经验证了底层模块的正确性。
缺点:在真正集成之前每一个独立的模块没有完全测试过。E.g., B and D
持续集成(Continuous Integration)
通常系统集成都会采用持续集成的策略,软件开发中各个模块不是同时完成,根据进度将完成的模块尽可能早的进行集成,有助于尽早发现Bug,避免集成中大量Bug涌现;而且容易定位Bug、修正Bug,最终提高软件开发的质量与效率。
单元测试﹑验收测试﹑回归测试﹑性能测试等基本概念
单元测试
定义:单元测试是对软件基本的组成单元进行独立的测试
时机:
- 单元测试和编码是同步进行
- 在TDD中,强调测试在先,编码在后
- 单元测试一般由开发人员完成,QA人员辅助
概念:模块、组件、单元
为何要进行单元测试
- 尽早发现错误
- 错误发现越早,成本越低
- 发现问题比较容易
- 修正问题更容易
- 检查代码是否符合设计和规范,有利于将来代码的维护
单元测试的目标
目标: 单元模块被正确编码
- 信息能否正确地流入和流出单元
- 在单元工作过程中,其内部数据能否保持其完整性,包括内部数据的形式、内容及相互关系不发生错误,全局变量在单元中的处理和影响
- 为限制数据加工而设置的边界处,能否正确工作
- 单元的运行能否做到满足特定的逻辑覆盖
驱动程序和桩程序
运行单元程序有时需要基于被测单元的接口,开发相应的驱动模块和桩模块。
驱动模块(drive):对底层或子层模块进行测试所编写的调用这些模块的程序。
桩模块(stub):对顶层或上层模块进行测试时所编写的替代下层模块的程序。
单元测试停止条件
- 单元测试用例设计已经通过评审
- 按照单元测试计划完成了所有规定单元的测试
- 达到了测试计划中关于单元测试所规定的覆盖率的要求
- 被测试的单元每千行代码必须发现至少3个错误
- 软件单元功能与设计相一致
- 在单元测试中发现的错误已经得到修改,各级缺陷修复率达到标准
功能测试
业务逻辑是关键
功能测试要点
- 每项功能符合实际要求
- 能接受正确的数据输入,对异常输入的容错处理
- 数据的输出结果准确,格式清晰,可以保存和读取
- 菜单、按钮操作正常、灵活,能处理一些异常操作
- 系统的各种状态按照业务流程而变化,并保持稳定
- 程序安装、启动正常,有相应的提示框、错误提示等
- 功能逻辑清楚,符合使用者习惯
- 系统的界面清晰、美观
- ……
功能测试的整体思路
客户需求为导向
性能测试(系统测试)
性能测试(performance test)就是为了发现系统性能问题或获取系统性能相关指标而进行的测试。
一般在真实环境、特定负载条件下,通过工具模拟实际软件系统的运行及其操作,同时监控性能各项指标,最后对测试结果进行分析来确定系统的性能状况。
性能测试目标
获取系统性能某些指标数据
验证系统是否达到用户提出的性能指标
发现系统中存在的性能瓶颈,优化系统的性能
性能测试类型
性能验证测试,验证系统是否达到事先已定义的系统性能指标、能否满足系统的性能需求
性能基准测试,在系统标准配置下获得有关的性能指标数据,作为将来性能改进的基准线
性能规划测试,在多种特定的环境下,获得不同配置的系统的性能指标,从而决定在系统部署时采用什么样的软、硬件配置
压力/负载/强度测试
压力测试(Stress test),也称为强度测试、负载测试。压力测试是模拟实际应用的软硬件环境及用户使用过程的系统负荷,长时间或超大负荷地运行测试软件,来测试被测系统的性能、可靠性、稳定性等。
在一种需要反常(如长时间的峰值)数量、频率或资源的方式下,执行可重复的负载测试,以检查程序对异常情况的抵抗能力,找出性能瓶颈或其它不稳定性问题。
并发性能测试
并发性能测试的过程也是一个负载测试过程,即逐渐增加并发虚拟用户数负载,直到系统出现性能瓶颈或者崩溃为止。
破坏性压力测试,通过不断加载的手段,快速造成系统的崩溃,让问题尽快地暴露出来
疲劳强度测试
采用系统稳定运行情况下能够支持的最大负载,持续长时间运行,以发现性能问题。
- 渗入测试(soak test),通过长时间运行,使问题逐渐渗透出来,从而发现内存泄漏、垃圾收集(GC)或系统的其他问题,以检验系统的健壮性
- 峰谷测试(peak-rest test),采用高低突变加载方式进行,先加载到高水平的负载,然后急剧降低负载,稍微平息一段时间,再加载到高水平的负载,重复这样过程,容易发现问题的蛛丝马迹,最终找到问题的根源
大数据量测试
独立的数据量测试:针对某些系统存储、传输、统计、查询等业务进行大数据量测试
综合数据量测试:和压力/负载性能测试、并发性能测试、疲劳性能测试相结合的综合测试方案
性能测试需求和指标
性能测试需求:用户对各项指标提出的明确需求;如果用户没有提出性能指标,则根据用户需求、测试设计人员的经验来设计各项测试指标。(需求+经验)
主要的性能指标:服务器的各项指标(CPU、内存占用率等)、后台数据库的各项指标、网络流量、响应时间
确定性能需求
只有具备了清楚而量化的性能指标,性能测试才能开始实施。
最终用户的体验,如2-5-10原则
商业需求,如“比竞争对手的产品好”
技术需求,如CPU使用率不超过70%
标准要求
响应时间是用户的关注点,容量和数据吞吐量是(产品市场团队)业务处理方面的关注点,而系统资源占用率是开发团队的技术关注点
性能的具体指标
- 数据传输的吞吐量(Transactions)
- 数据处理效率(Transactions per second)
- 数据请求的响应时间(Response time)
- 内存和CPU使用率
- 连接时间(Connect Time)、发送时间(Sent Time)
- 处理时间(Process Time)、页面下载时间
- 第一次缓冲时间
- 每秒(SSL)连接数
- 每秒事务总数、每秒下载页面数
- 每秒点击次数、每秒HTTP 响应数
- 每秒重试次数
负载(Workload)
- 每秒处理请求数 (Request Per Second, RPS)
- 并发连接数 (Simultaneous Connections)
- 思考时间(thinking time),用户发出请求之间的间隔时间
- 加载的循环次数或持续时间
- 加载的方式或模式,如均匀加载、峰值交替加载等
关键业务选择
不可能/不需要对Web应用系统的所有功能进行性能测试,而是根据业务的实际操作情况和技术的角度来分析,选择关键业务
性能测试工具
Jmeter、LoadRunner、Jprofiler
验收测试
验收测试 (Acceptance Test): 在软件产品完成了系统功能和非功能测试之后、产品发布之前所进行的软件测试活动它是技术测试的最后一个阶段,也称为交付测试。
测试内容
前提:系统或软件产品已通过了系统测试的软件系统。
测试内容:
验证系统是否达到了用户需求规格说明书(可能包括项目或产品验收准则)中的要求,测试尽可能地发现软件中存留的缺陷,从而为软件进一步改善提供帮助,并保证系统或软件产品最终被用户接受。
主要包括易用性测试、安装测试、文档(如用户手册)测试等几个方面的内容。
测试步骤
- 制定测试计划及验收通过准则,通过客户评审
- 设计测试用例并通过评审
- 准备测试环境与数据,执行测试用例,记录测试结果
- 分析测试结果,根据验收通过准则分析测试结果,作出验收是否通过及测试评价。
- 测试项目通过;
- 测试项目没有通过,但存在变通方法,在维护后期或下一个版本改进;
- 测试项目没有通过,并且不存在变通方法,需要很大的修改;
- 测试项目无法评估或者无法给出完整的评估,此时须给出原因.
- 提交测试报告
验收标准和注意事项
验收测试完成标准:
- 完全执行了验收测试计划中的每个测试用例
- 在验收测试中发现的错误已经得到修改并且通过了测试、或经过评估留待下一版本中修改
- 完成软件验收测试报告
注意事项:
- 必须编写正式的、单独的验收测试报告
- 验收测试必须在实际用户运行环境中进行
- 由用户和测试部门共同执行
α/β测试
α 测试: 开发公司组织内部人员模拟各类用户行为对即将面市的软件产品(称为α版本)进行的测试,试图发现错误并修正。
β 测试:组织外部的典型用户在日常工作中实际使用β版本,并要求用户报告异常情况、反馈使用意见。然后软件开发公司再对β版本进行改错和完善。
回归测试
回归测试的目的
- 所做的修改达到了预定的目的,如错误得到了改正,新功能得到了实现,能够适应新的运行环境等;
- 不影响软件原有功能的正确性。
一旦程序某些区域被修改了,就可能影响其它区域,导致受影响的区域出现新的缺陷(回归缺陷)。如果这时没有回归测试,产品就带着这样的回归缺陷被发布出去了,造成严重后果。回归测试就是为了发现回归缺陷而进行的测试。
回归测试策略
- 再测试修改的部分
- 再测试全部用例
- 基于风险选择测试
- 基于操作剖面选择测试
- 更智能的选择方法
软件测试
对Junit,EasyMock jprofiler , jmeter,QTP等测试功能和工具的了解
作业错题
关于软件测试与软件开发过程的关系,下列描述哪些是正确的?
A、没有开发过程就没有测试过程
B、测试过程是为保证开发过程的产出进行验证和确认的一系列活动
C、不同的软件开发过程模型中,测试在其中所处的位置不同
D、开发比测试更重要
答案:ABC
W模型是基于“尽早地和不断地进行软件测试”的原则。 答案:×
下列哪项测试是对Web网站的功能测试?
A、安全性测试
B、平台测试
C、连接速度测试
D、链接测试
答案:D
基于JUnit设计单元测试脚本时,用于支持同时执行多个测试用例的运行器是:
A、Categories
B、TestCase
C、Parameterized
D、Suite
答案:D
下列哪几项可以用来检查需求?
A、需求规格说明书
B、测试计划书
C、产品说明书
D、测试用例
答案:AD
测试计划的要点包括以下哪些?
A、计划调整
B、进度安排
C、模拟测试结果
D、确定测试范围
答案:BD
报告bug时注意的问题有哪些?
A、提供软件测试环境
B、注意测试结果
C、附加必要的截图和文件
D、不要出现错别字
答案:ACD
下列哪些工具是性能测试工具?
A、JUnit
B、JMeter
C、JProfiler
D、LoadRunner
答案:BCD
单元测试通过的标准是什么?
A、程序通过所有的单元测试用例
B、语句覆盖流程达到100%
C、分支覆盖率达到85%
答案:ABC
选择集成测试方式时,需要着重考虑以下哪些问题?
A、哪些模块是集成测试的重点
B、模块接口的重要程度
C、开发驱动模块和桩模块的复杂度
D、采用哪种测试设计技术检测每个接口比较合适
答案:ABD
本文来自博客园,作者:Un-Defined,转载请保留本文署名Un-Defined,并在文章顶部注明原文链接:https://www.cnblogs.com/EIPsilly/p/15728186.html