“阅读本文大概需要16分钟。
你好,我是测试蔡坨坨。
众所周知,测试用例是每个测试人员都绕不开的话题,也是大家习以为常的事情,无论是功能测试、性能测试,还是自动化测试,都会涉及到用例设计,可以说测试用例是一切测试的基础。
虽然有时候公司并没有强制要求写测试用例,但至少测试点是必不可少的。几乎所有测试相关的专栏、博客、公众号都会提及用例设计,其重要性不言而喻。即便如此,还有许多从业者设计用例的方式仅仅靠经验积累,虽然他们知道用例的设计需要从软件功能、性能、易用性、可靠性、信息安全性、维护性、兼容性、可移植性等多方面考虑,但是并没有形成一套通用的体系结构。
所以,本篇将会从体系的角度来聊一聊测试用例的设计,深挖用例设计的底层逻辑。
前段时间收到一个朋友私信询问,接口测试用例怎么设计?当时他已经是个熟练的功能测试人员,换了种场景就不会写测试用例?本质上还是未能掌握用例设计的通用逻辑。

想必大家在面试的时候或多或少有被问到“朋友圈点赞功能怎么测试?、“淘宝购物车如何测试?”,甚至是一些非软件物品测试,比如“这个杯子怎么测试?”、“电梯怎么测试?”等类似的问题。其实这类问题主要用来考察应聘者的测试思维,以及设计测试用例的角度与思考问题的全面性。
对于此类面试题,其实是有一定套路的,只要你掌握了相关方法,那么任何物品都可以进行测试,并且设计出相对全面的测试用例。
先给出通用公式:场景法(交互分析) - 等价类划分 - 边界值 - 用例组合
在测试之前,我们要深入了解被测对象,也就是需求分析,通常我们会根据PRD(产品需求文档)去构建测试用例,比如:水杯的PRD就是“这是一个水杯”,但是这里面存在一个问题,业务的质量特性包括显性特性和隐性特性,而PRD往往只给出显性需求,甚至有时候连显性特征都不齐全,这就很考验产品同学。因此我们需要通过其他方法去挖掘更多的隐性特性,以得到更加全面的特性,而不仅仅通过需求文档直接生成测试用例。
我们要明白几乎所有被测对象都是可以被交互的,交互时的情景便形成了场景,用例设计其实就是寻找交互点,从而转化为输入域和输出域。比如我们与水杯的交互:看起来(外观,应用到软件中就是前端UI界面)、拿起来(功能/性能/安全/易用)、装起来(功能/性能/兼容/安全/易用/可靠)、喝起来(功能/性能/兼容/安全/易用/可靠)、放起来(性能/兼容/安全/可维护/可移植)。
通常来说,我们要从功能、性能、安全、易用性、可靠性、兼容性、维护性、可移植性等多方面考虑,其实指的就是单个交互输入域的完整性。还是拿杯子举例:
以上举例主要是提供思路,起到抛砖迎玉的作用,用例仅供参考,并不是很全面。
当我们碰到一个不熟悉的场景时,如果有了这套方法论,就可以帮助我们提供更全面的思考以及更完整的输入域。这里提供一种较好的描述方式对交互进行描述,就是用产品质量的八大特性,即功能性(是否满足客户需求,三大核心:正确性、完备性、适合性)、性能效率(时间特性、资源占用)、易用性(用户理解、操作简单)、可靠性(能够正常维持产品特性的程度)、安全性(输入输出安全、交互安全、内容安全,比如密码输入框掩码、文件加密传输、重要信息掩码)、维护性(因环境变化需要作出调整的难易程度,比如用开关控制功能是否可用)、兼容性(与环境的共存,交互对象的互操作,比如不同浏览器之间的兼容、不同操作系统之间的兼容)、可移植性(从一个环境移到另一个环境的难易程度)。
复用这套方法,我们就可以找到更多的隐性特性,显性特性就是我们上面讨论的那些,当然,我们能够识别隐性特性,还取决于我们对业务的熟练程度。再次拿杯子举例,比如水杯的设计还要考虑用户群体,啤酒杯、红酒杯、白酒杯它们的容量和形状都是不一样的,所以在列举输入域的时候,理应结合需求背景、业务特性和用户群体。
做完交互分析后,再使用等价类划分将输入域按某个维度进行有效的归类,比如:可乐、雪碧等对于常规水杯来说是同类物体,没有必要穷举,于是将它们都归类为碳酸饮料。然后在等价类的基础上再使用边界值分析法提取单个输入域分类的有效代表值,比如:0℃(在1个标准大气压下,纯净的冰水混合物温度为0℃)和100℃(沸水的温度为100℃)。至于为什么要这么做,在第二小节「用例的本质」中将会给出答案。
最后进行用例组合,就是对这些代表值按分类做交叉考虑。比如:常温的碳酸饮料、冰冻的碳酸饮料、冰冻的水、沸腾的水、沸腾的碳酸饮料 ……
我们再回到刚开始的那个问题——“接口测试用例怎么设计?”,套用这个公式,我们可以通过发起接口调用,检查是否能调通以及返回内容的正确性,以验证功能是否实现;可以高频次的发起请求以检查性能是否满足要求;可以尝试提交未经授权的请求,以检验它的安全性 ……
理论上来说,从输入端要保证查出程序中所有的错误,只能采用穷举的方法,把所有可能的输入都作为测试情况考虑。但实际上测试情况有无穷多个,我们不仅要测试所有合法的输入,还要测试不合法的输入,所以穷举测试在很多时候是不可行的。也就是说“完美的测试是不可能的”,那是不是代表测试是靠运气?并不然。
实际的测试工作需要我们采用各种技术来有针对性地进行测试,通过制定测试案例指导测试实施,保证软件测试有组织、按步骤以及有计划的进行,也就是我们需要把无限的输入域,变成有限的、有代表性的输入集。测试的意义并不是找到所有的缺陷,而是找到对业务有价值的缺陷。
好的测试用例,是能够用较少的用例,找到尽可能多的有价值的问题。
因此这也解释了为什么会出现等价类划分法、边界值分析法等许许多多的用例设计方法。
我们再来回顾一下第一小节给出的通用公式:场景法(交互分析) - 等价类划分 - 边界值 - 用例组合
在这个小结,将会介绍这个通用公式用到了哪些具体的用例设计方法。
很显然,在这一步骤中用到的方法就是场景法。
什么是场景法?
现在的软件几乎都是用事件触发来控制流程的,事件触发时的情景便形成了场景,而同一事件不同的触发顺序和处理结果就形成了事件流。这种在软件设计方面的思想引入到软件测试中,可以生动形象描绘出事件触发时的情景,有利于测试人员设计测试用例,同时使用例更容易理解和执行。
场景法使用被测软件与用户或其他系统之间的交互序列模型来测试被测软件的使用流程。
简单来说,场景法就是尽可能真实全部的模拟用户操作,比如:订单、发货、商品状态变化。
场景法主要基于:
应该包含以下场景:

举栗:以自动取款机ATM系统为例
基本场景:
成功从账户取款
可选场景:

依据需求将输入划分为若干等价类,从等价类中选定少数代表性的数据作为测试用例,如果该用例通过,则表明整个等价类通过测试。
适用于有无限多种输入,我们不可能完成穷举测试,等价类可以使我们用比较少的测试用例尽可能多的将功能覆盖,从而把无限的穷举输入转化为有限的等价类有代表性的输入,用少量的代表性测试数据来取得较好的测试结果。
考虑这两种等价类是因为软件不仅要能接收合理的数据,也要能经受各种意外的考验,这样的测试才能确保软件具有更高的可靠性。
常见的划分方法包括:按区间划分、按数值划分、按数值集划分、按限制条件划分、按处理方式划分。
日期输入框,要求用户输入以年月标识的日期,输入范围在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变量的软件输入域,就会有略小于最小值、最小值、正常值、最大值、略大于最大值五种选择。
三值边界测试:对于三值边界测试,就有略小于最小值、最小值、略大于最小值、正常值、略小于最大值、最大值、略大于最大值七种选择。
PS:0/空,N/A,null是一个特殊值,我们在考虑边界值的时候同时也要考虑这个特殊值。
用例组合就是对以上代表值按分类做交叉考虑,其中会用到判定表、因果图、正交试验法等,这些方法就是告诉我们如何做交叉考虑的方法论。
用于展示输出条件与输出结果的对应关系。
分析和表述若干输入条件下,被测对象针对这些输入做出的响应的一种工具。
在遇到复杂业务逻辑时可以利用该表理清逻辑关系,适用于输入框有关联的场景,例如:用户名输入框和密码输入框。
规则:动作项和条件项组合在一起,形成的业务逻辑处理规则。
登录模块为例

因果图是一种简化了的逻辑图,能直观地表明输入条件和输出动作之间的因果关系。
主要组成部分:原因、中间节点、结果。
操作步骤:
PS:若能直接得到判定表,可以直接根据判定表设计测试用例,即可以跳过绘制因果图部分。
考试系统,作业达到80分且已确认可进入下一阶段学习
因果图:

将因果图转化成判定表:

Word字体样式:
大红宋体 | 大红黑体 | 大红楷体 | 中红宋体 | 中红黑体 | 中红楷体 | 小红宋体 | 小红黑体 | 小红楷体 |
|---|---|---|---|---|---|---|---|---|
大绿宋体 | 大绿黑体 | 大绿楷体 | 中绿宋体 | 中绿黑体 | 中绿楷体 | 小绿宋体 | 小绿黑体 | 小绿楷体 |
大蓝宋体 | 大蓝黑体 | 大蓝楷体 | 中蓝宋体 | 中蓝黑体 | 中蓝楷体 | 小蓝宋体 | 小蓝黑体 | 小蓝楷体 |
通常来说,使用以上测试方法就能应对绝大多数的场景。
除此之外,还有一些其他的测试方法,同样可以给测试人员带来较大的帮助,这里选择性地介绍几个。
基于经验和直觉推测程序中所有可能存在的各种错误,从而有针对性的设计测试用例。
二八原则:80%的问题往往出现在20%的模块。
基本思想:列举出程序中所有可能有的错误和容易发生错误的特殊情况,根据他们选择测试用例。
基本要素:
软件错误类型:
可参考往期文章「五分钟搞懂探索式测试」
通过设计相应的检查点,并按照检查点进行测试验证的一种测试方法。检查表中的检查项来源于以往的测试经验总结。检查表用于支持各种测试类型,包括功能和非功能测试。
举栗:基于代码检查表的测试
在代码审查阶段,代码检查表将常见的错误进行分类,在每一类错误下列举出容易出错的位置和在以往工作中的典型错误,将其以清单的形式展示,比如:NullPointerException空指针异常通常是因为没有做非空判断、switch中是否有default ……
检查点 | 检查项 | 结果 |
|---|---|---|
格式规范性 | 嵌套的IF语句是否正确地缩进、注释是否准确并有意义、整体上是否遵循全套的编程标准 | |
判断和转移 | 正确的条件是否经判断、用于判断的是否是正确的变量 | |
性能 | 每个逻辑是否实现最佳编码 | |
逻辑性 | 全部设计是否都已实现、代码实现是否与设计一致 | |
…… |
测试用例是测试的基础,测试用例设计是一个很大的话题,还有很多内容值得探讨,由于时间关系,暂且讨论到这里,同时,我相信随着测试理论和技术的发展,将来一定会有更多更智能的用例设计策略出现,让我们共同期待它的到来吧。
以上,完。
脚踏实地,仰望星空,和坨坨一起学习软件测试,升职加薪!