测试用例设计的底层逻辑
测试用例设计的底层逻辑
蔡坨坨转载请注明出处❤️
作者:测试蔡坨坨
原文链接:caituotuo.top/aa1e1162.html
你好,我是测试蔡坨坨。
众所周知,测试用例是每个测试人员都绕不开的话题,也是大家习以为常的事情,无论是功能测试、性能测试,还是自动化测试,都会涉及到用例设计,可以说测试用例是一切测试的基础。
虽然有时候公司并没有强制要求写测试用例,但至少测试点是必不可少的。几乎所有测试相关的专栏、博客、公众号都会提及用例设计,其重要性不言而喻。即便如此,还有许多从业者设计用例的方式仅仅靠经验积累,虽然他们知道用例的设计需要从软件功能、性能、易用性、可靠性、信息安全性、维护性、兼容性、可移植性等多方面考虑,但是并没有形成一套通用的体系结构。
所以,本篇将会从体系的角度来聊一聊测试用例的设计,深挖用例设计的底层逻辑。
1 万物皆可测试
前段时间收到一个朋友私信询问,接口测试用例怎么设计?当时他已经是个熟练的功能测试人员,换了种场景就不会写测试用例?本质上还是未能掌握用例设计的通用逻辑。
想必大家在面试的时候或多或少有被问到“朋友圈点赞功能怎么测试?、“淘宝购物车如何测试?”,甚至是一些非软件物品测试,比如“这个杯子怎么测试?”、“电梯怎么测试?”等类似的问题。其实这类问题主要用来考察应聘者的测试思维,以及设计测试用例的角度与思考问题的全面性。
对于此类面试题,其实是有一定套路的,只要你掌握了相关方法,那么任何物品都可以进行测试,并且设计出相对全面的测试用例。
先给出通用公式:场景法(交互分析) - 等价类划分 - 边界值 - 用例组合
在测试之前,我们要深入了解被测对象,也就是需求分析,通常我们会根据PRD(产品需求文档)去构建测试用例,比如:水杯的PRD就是“这是一个水杯”,但是这里面存在一个问题,业务的质量特性包括显性特性和隐性特性,而PRD往往只给出显性需求,甚至有时候连显性特征都不齐全,这就很考验产品同学。因此我们需要通过其他方法去挖掘更多的隐性特性,以得到更加全面的特性,而不仅仅通过需求文档直接生成测试用例。
我们要明白几乎所有被测对象都是可以被交互的,交互时的情景便形成了场景,用例设计其实就是寻找交互点,从而转化为输入域和输出域。比如我们与水杯的交互:看起来(外观,应用到软件中就是前端UI界面)、拿起来(功能/性能/安全/易用)、装起来(功能/性能/兼容/安全/易用/可靠)、喝起来(功能/性能/兼容/安全/易用/可靠)、放起来(性能/兼容/安全/可维护/可移植)。
通常来说,我们要从功能、性能、安全、易用性、可靠性、兼容性、维护性、可移植性等多方面考虑,其实指的就是单个交互输入域的完整性。还是拿杯子举例:
- 功能:能否装水;除了装水,能否装其他液体,如:碳酸饮料、酒精、茶、咖啡等;是否有刻度……
- 性能:能否装100℃的水;能否装0℃的冰水;装满水,放几天,是否会漏水;杯子上的涂料是否容易脱落;是否易碎 ……
- 安全:制作杯子的材料对人体是否有害;给杯子加热是否会融化、爆炸;杯子是否有缺口,会划伤嘴巴;内壁的涂料是否会溶解到水中;杯子破碎后是否会对使用者造成伤害 ……
- 易用性:是否容易烫伤;把手是否好端;杯子里的水是否容易喝到;是否有防滑措施 ……
- ……
以上举例主要是提供思路,起到抛砖迎玉的作用,用例仅供参考,并不是很全面。
当我们碰到一个不熟悉的场景时,如果有了这套方法论,就可以帮助我们提供更全面的思考以及更完整的输入域。这里提供一种较好的描述方式对交互进行描述,就是用产品质量的八大特性
,即功能性
(是否满足客户需求,三大核心:正确性、完备性、适合性)、性能效率
(时间特性、资源占用)、易用性
(用户理解、操作简单)、可靠性
(能够正常维持产品特性的程度)、安全性
(输入输出安全、交互安全、内容安全,比如密码输入框掩码、文件加密传输、重要信息掩码)、维护性
(因环境变化需要作出调整的难易程度,比如用开关控制功能是否可用)、兼容性
(与环境的共存,交互对象的互操作,比如不同浏览器之间的兼容、不同操作系统之间的兼容)、可移植性
(从一个环境移到另一个环境的难易程度)。
复用这套方法,我们就可以找到更多的隐性特性,显性特性就是我们上面讨论的那些,当然,我们能够识别隐性特性,还取决于我们对业务的熟练程度。再次拿杯子举例,比如水杯的设计还要考虑用户群体,啤酒杯、红酒杯、白酒杯它们的容量和形状都是不一样的,所以在列举输入域的时候,理应结合需求背景、业务特性和用户群体。
做完交互分析后,再使用等价类划分将输入域按某个维度进行有效的归类,比如:可乐、雪碧等对于常规水杯来说是同类物体,没有必要穷举,于是将它们都归类为碳酸饮料。然后在等价类的基础上再使用边界值分析法提取单个输入域分类的有效代表值,比如:0℃(在1个标准大气压下,纯净的冰水混合物温度为0℃)和100℃(沸水的温度为100℃)。至于为什么要这么做,在第二小节「用例的本质」中将会给出答案。
最后进行用例组合,就是对这些代表值按分类做交叉考虑。比如:常温的碳酸饮料、冰冻的碳酸饮料、冰冻的水、沸腾的水、沸腾的碳酸饮料 ……
我们再回到刚开始的那个问题——“接口测试用例怎么设计?”,套用这个公式,我们可以通过发起接口调用,检查是否能调通以及返回内容的正确性,以验证功能是否实现;可以高频次的发起请求以检查性能是否满足要求;可以尝试提交未经授权的请求,以检验它的安全性 ……
2 用例的本质
理论上来说,从输入端要保证查出程序中所有的错误,只能采用穷举的方法,把所有可能的输入都作为测试情况考虑。但实际上测试情况有无穷多个,我们不仅要测试所有合法的输入,还要测试不合法的输入,所以穷举测试在很多时候是不可行的。也就是说“完美的测试是不可能的”,那是不是代表测试是靠运气?并不然。
实际的测试工作需要我们采用各种技术来有针对性地进行测试,通过制定测试案例指导测试实施,保证软件测试有组织、按步骤以及有计划的进行,也就是我们需要把无限的输入域,变成有限的、有代表性的输入集。测试的意义并不是找到所有的缺陷,而是找到对业务有价值的缺陷。
好的测试用例,是能够用较少的用例,找到尽可能多的有价值的问题。
因此这也解释了为什么会出现等价类划分法、边界值分析法等许许多多的用例设计方法。
3 通用公式中的用例设计方法
我们再来回顾一下第一小节给出的通用公式:场景法(交互分析) - 等价类划分 - 边界值 - 用例组合
在这个小结,将会介绍这个通用公式用到了哪些具体的用例设计方法。
场景法(交互分析)
很显然,在这一步骤中用到的方法就是场景法
。
什么是场景法?
现在的软件几乎都是用事件触发来控制流程的,事件触发时的情景便形成了场景,而同一事件不同的触发顺序和处理结果就形成了事件流。这种在软件设计方面的思想引入到软件测试中,可以生动形象描绘出事件触发时的情景,有利于测试人员设计测试用例,同时使用例更容易理解和执行。
场景法使用被测软件与用户或其他系统之间的交互序列模型
来测试被测软件的使用流程。
简单来说,场景法就是尽可能真实全部的模拟用户操作,比如:订单、发货、商品状态变化。
场景法主要基于:
- 业务/需求层面:对所测软件的重要功能、业务逻辑、行业背景深入理解。
- 技术层面:基于等价类划分,有效等价类(模拟用户正确的操作);无效等价类(模拟用户错误的操作)。
应该包含以下场景:
- 基本场景/基本流/正确流/有效流:模拟用户正确的操作流程。
- 可选场景/备选流/错误流/无效流:模拟用户错误的操作流程,非正常的使用、极端或者压力条件和异常等。
举栗:以自动取款机ATM系统为例
基本场景:
成功从账户取款
可选场景:
- 银行卡不能被ATM机识别,被拒绝
- 用户输入密码错误不多于2次
- 用户输入密码错误3次,冻结并吐卡
- 用户选择存款或转账,不选择取款
- ATM中现金不足
- 用户输入不符合面额的取款金额
- 用户输入的取款金额超过每日最大取款金额
- 用户银行账户中的金额不足
- ……
等价类划分
什么是等价类划分法
依据需求将输入划分为若干等价类,从等价类中选定少数代表性的数据作为测试用例,如果该用例通过,则表明整个等价类通过测试。
使用场景
适用于有无限多种输入,我们不可能完成穷举测试,等价类可以使我们用比较少的测试用例尽可能多的将功能覆盖,从而把无限的穷举输入转化为有限的等价类有代表性的输入,用少量的代表性测试数据来取得较好的测试结果。
等价类的划分
- 有效等价类:合理的、有意义的输入数据构成的集合,对于需求规格说明书是合法的,利用有效等价类可检验程序是否实现了规格说明中所规定的功能和性能。
- 无效等价类:对于程序的规格说明来说是不合理或无意义的输入数据所构成的集合。
考虑这两种等价类是因为软件不仅要能接收合理的数据,也要能经受各种意外的考验,这样的测试才能确保软件具有更高的可靠性。
划分等价类的原则
常见的划分方法包括:按区间划分、按数值划分、按数值集划分、按限制条件划分、按处理方式划分。
- 若输入条件规定了取值范围(1-120s)或值的个数(手机号11个字符),可以确定一个有效等价类(范围内)和两个无效等价类(大于、小于)
- 若输入条件规定了“必须如何”,可确定一个有效等价类和一个无效等价类
- 若输入条件是一个布尔值,可确定一个有效等价类(true)和一个无效等价类(false)
- 若输入条件规定了一组值(假定n个),需要对每一个输入值分别处理,可确定n个有效等价类和一个无效等价类
- 若输入数据必须遵守某个规则,可确定一个有效等价类(符合规则)和若干个无效等价类(从不同角度违反规则)
- 在确知已划分的等价类中,各个元素在程序处理中的方式不同时,则应再将等价类进一步分为更小的等价类
举栗
日期输入框,要求用户输入以年月标识的日期,输入范围在2000年1月至2100年12月之间,格式为200001。
输入条件 | 有效等价类 | 无效等价类 |
---|---|---|
日期的类型及长度 | 6位数字字符(202210) | 有非数字字符(20221A);小于6位数字字符(20221);大于6位数字字符(20221000) |
年份范围 | 在2000至2100之间(202210) | 小于2000(19990222);大于2100(220010) |
月份范围 | 在01至12之间 | 等于00(202200);大于12(202213) |
等价类与测试用例之间的关系:可以由每一个测试用例覆盖一个特定的等价类,也可以由一个测试用例对应多个等价类。
边界值
什么是边界值分析法
边界值测试是源于人们长期以来的测试工作经验所提出的一个关键假设:错误更容易发生在输入域的边界或者说极值附近,而非输入域的中间部分。
边界值分析法是对等价类划分法的补充,一遍都是从等价类的边缘去寻找错误。
边界值分析法的分类
边界值的选择可以分为二值边界测试和三值边界测试。
二值边界测试:如果有一个n变量的软件输入域,就会有略小于最小值、最小值、正常值、最大值、略大于最大值五种选择。
三值边界测试:对于三值边界测试,就有略小于最小值、最小值、略大于最小值、正常值、略小于最大值、最大值、略大于最大值七种选择。
举栗
- 微信红包:最小金额0.01,最大金额200元,边界值就是0、0.01、0.02、199.99、200、200.01
- 一个文本框输入区域包括0-255个字符,边界值就是-1、0、1、254、255、256
PS:0/空,N/A,null是一个特殊值,我们在考虑边界值的时候同时也要考虑这个特殊值。
用例组合
用例组合就是对以上代表值按分类做交叉考虑,其中会用到判定表、因果图、正交试验法等,这些方法就是告诉我们如何做交叉考虑的方法论。
判定表
什么是判定表?
用于展示输出条件与输出结果的对应关系。
分析和表述若干输入条件下,被测对象针对这些输入做出的响应的一种工具。
在遇到复杂业务逻辑时可以利用该表理清逻辑关系,适用于输入框有关联的场景,例如:用户名输入框和密码输入框。
判定表的组成
- 条件
- 条件桩(condition stub):需求规格说明书中定义的被测对象的所有输入。
- 条件项(condition entry):针对条件桩所有可能输入数据的真假值。
- 动作
- 动作桩(action stub):针对条件,被测对象可能采取的所有操作。
- 动作项(action entry):针对动作桩,被测对象响应的可能取值。
规则:动作项和条件项组合在一起,形成的业务逻辑处理规则。
判定表的建立
- 理解需求,确定条件桩、动作桩。
- 设计及优化判定表。
- 填写动作项。
- 根据判定表输出结果的表现,进行判定表的合并(非必须),简化判定表;如果输出相同,在对应输入中,有且只有一个条件的取值对动作不产生任何影响则可合并。
举栗
登录模块为例
条件桩:用户名正确、密码正确
动作桩:登录成功、提示用户名或密码错误
因果图
什么是因果图?
因果图是一种简化了的逻辑图,能直观地表明输入条件和输出动作之间的因果关系。
主要组成部分:原因、中间节点、结果。
操作步骤:
- 分析程序的规格说明书中哪些是原因,哪些是结果。所谓原因,是指输入条件或输入条件的等价类,而结果是指输出条件,给每一个原因和结果赋一个表示符。
- 分析程序规格说明书中的语义,确定原因与原因,原因与结果之间的关系,画出因果图。
- 由于语法环境的限制,一些原因与原因之间,原因与结果之间的组合不能出现。对于这种特殊情况,在因果图中用一些记号表明约束或限制条件。
- 将因果图转化为判定表。
- 根据判定表的每一列设计测试用例。
PS:若能直接得到判定表,可以直接根据判定表设计测试用例,即可以跳过绘制因果图部分。
举栗
考试系统,作业达到80分且已确认可进入下一阶段学习
因果图:
将因果图转化成判定表:
正交试验法
什么是正交试验法?
- 正交试验法是研究多因素、多水平的一种试验法
- 它是利用正交表来对试验进行设计
- 通过少数的试验替代全面试验,根据正交表的正交性从全面试验中挑选适量的、有代表性的点进行试验,这些有代表性的点具备了“均匀分散,整齐可比”的特点
举栗
Word字体样式:
- 字体大小:大、中、小
- 字体颜色:红、绿、蓝
- 字体样式:宋体、黑体、楷体
大红宋体 |
大红黑体 | 大红楷体 | 中红宋体 | 中红黑体 | 中红楷体 | 小红宋体 | 小红黑体 | 小红楷体 |
---|---|---|---|---|---|---|---|---|
大绿宋体 | 大绿黑体 | 大绿楷体 | 中绿宋体 | 中绿黑体 |
中绿楷体 | 小绿宋体 | 小绿黑体 | 小绿楷体 |
大蓝宋体 | 大蓝黑体 | 大蓝楷体 | 中蓝宋体 | 中蓝黑体 | 中蓝楷体 | 小蓝宋体 | 小蓝黑体 | 小蓝楷体 |
4 其他用例设计方法
通常来说,使用以上测试方法就能应对绝大多数的场景。
除此之外,还有一些其他的测试方法,同样可以给测试人员带来较大的帮助,这里选择性地介绍几个。
错误推断法
基于经验和直觉推测程序中所有可能存在的各种错误,从而有针对性的设计测试用例。
二八原则:80%的问题往往出现在20%的模块。
基本思想:列举出程序中所有可能有的错误和容易发生错误的特殊情况,根据他们选择测试用例。
基本要素:
对开发的开发习惯很熟悉。
对同类型项目业务非常熟悉。
软件错误类型:
- 软件需求错误
- 需求不合理
- 需求不全面、不明确
- 逻辑错误
- 文档有误
- 功能和性能错误
- 需求规格说明中规定的功能实现不正确、存在未实现或冗余的情况
- 性能未满足规定的要求
- 为用户提供的信息不准确
- 异常情况处理有误
- 软件结构错误
- 程序控制流或控制顺序有误
- 处理过程有误
- 数据错误
- 数据定义或数据结构有误
- 数据存取或数据操作有误
- 软件实现和编码错误
- 编码错误或按键错误
- 违反编码要求和标准,例如语法错误、数据名错误、程序逻辑有误等
- 软件集成错误
- 软件内部接口或外部接口有误
- 软件各相关部分在时间配合、数据吞吐量等方面不协调
探索式测试
可参考往期文章「五分钟搞懂探索式测试」
基于检查表的测试
通过设计相应的检查点,并按照检查点进行测试验证的一种测试方法。检查表中的检查项来源于以往的测试经验总结。检查表用于支持各种测试类型,包括功能和非功能测试。
举栗:基于代码检查表的测试
在代码审查阶段,代码检查表将常见的错误进行分类,在每一类错误下列举出容易出错的位置和在以往工作中的典型错误,将其以清单的形式展示,比如:NullPointerException空指针异常通常是因为没有做非空判断、switch中是否有default ……
检查点 | 检查项 | 结果 |
---|---|---|
格式规范性 | 嵌套的IF语句是否正确地缩进、注释是否准确并有意义、整体上是否遵循全套的编程标准 | |
判断和转移 | 正确的条件是否经判断、用于判断的是否是正确的变量 | |
性能 | 每个逻辑是否实现最佳编码 | |
逻辑性 | 全部设计是否都已实现、代码实现是否与设计一致 | |
…… |
测试用例是测试的基础,测试用例设计是一个很大的话题,还有很多内容值得探讨,由于时间关系,暂且讨论到这里,同时,我相信随着测试理论和技术的发展,将来一定会有更多更智能的用例设计策略出现,让我们共同期待它的到来吧。