测试用例设计背后的底层逻辑你一定不知道

news2024/12/23 8:23:41

目录

前言

1、万物皆可测

2、用例的本质

3、业务建模

4、其他一些测试法

总结:


前言

测试用例是每位测试人员都绕不开的话题,也是大家习以为常的事情。几乎所有测试相关的公众号、博客、专栏,都会提及测试用例,由此可见它的重要性。但是,有许多从业者,对测试用例的设计仍然依靠经验积累,即使知道用例要从功能、性能、安全等多方面考虑,也仅限于对字面的理解,未形成体系化的整理。所以,今天我更多会从系统的角度,来和大家一起看看用例设计背后的底层逻辑。

1、万物皆可测

曾经有一位小伙伴问我:接口要怎么测?当时他已经是一位很熟练的功能测试人员了,之所以在更换一种场景之后不知如何应对,还是因为未能掌握用例设计的通用逻辑。类似的问题还有:一个服务要怎么测、SDK 要怎么测等等。

首先,我要说一点:万物皆可测。在开始测试之前,我们需要深入去了解我们的测试对象,用互联网的话说,就是“业务分析”。通常,我们会根据 PRD(产品需求文档) 去构建测试用例,但这里面的问题是,业务的质量特性包含显性特性和隐性特性,而 PRD 往往只有最表层的显性特性(这很考验产品人员的能力,有些甚至连显性特性都不齐全)。一般而言,能通过各类文档中直接生成的用例,不到完整用例集的十分之一。所以这就需要我们通过其他的方法,来分析出更加全面的特性。

举个例子,过往的测试面经里有一个经典问题:要怎么测试一个水杯(不知道现在是否还有面试官问这个问题)。它的 “PRD” 只有一句:这是个水杯。这个问题考验的就是我们对测试对象的分析能力。我这里给出一条万能公式:交互分析->等价划分->边界测试->用例组合。接下来就以水杯为例,来具体看下如何运用这个公式。

我们要知道,所有的测试对象,都是可以被交互的。我们的测试用例设计,其实就是在寻找“交互点”,而后转化为输入域和输出域。比如,我们和水杯的交互点有:

  • 纯看着:外观
  • 拿起来:功能/效率/安全/易用
  • 装东西:功能/效率/兼容/安全/易用/可靠
  • 喝东西:功能/效率/兼容/安全/易用/可靠
  • 放起来:效率/兼容/安全/可维护/可移植

通常我们说的“要从功能、性能、安全等多方面考虑”,其实指的就是单个交互输入域的完整性。比如,对于水杯“装东西”这个交互:

  • 从功能上考虑,要能够正常盛放被装物品(正确性),要能够装入开水、凉水、茶、碳酸饮料(完备性),并且容量足够(适合性)。
  • 从安全上考虑,如果我装的是开水,杯体是否会烫手。
  • 从可靠上考虑,长时间盛装液体,是否会漏水。
  • ......

当我们面临一个不熟悉的场景时,难免会无从下手。如果我们有一套方法论,就可以帮助我们提供更全面的思考,得到更完整的输入域。我引用一个我认为比较好的一种描述法,即产品质量的八个特性

  • 功能:是否满足用户需求,核心三要素:正确性、完备性、适合性。
  • 效率:在软件中可以理解为性能,包括时间特性、资源占用。
  • 兼容:与环境的共存、交互对象的互操作。
  • 易用:用户理解、操作需要付出多少努力。
  • 可靠:能够正常维持产品特性的程度或概率。
  • 安全:输入输出安全、内容安全、交互安全。
  • 可维护:因环境变化时需要做出调整的难易度。
  • 可移植:从一个环境移到另一个环境的难易度。

通过复用这套方法论,我们就可以在面对不同的测试对象时,尽量找到更多的“隐性特性”(显性特性已经明明白白写给你啦)。此外,我们能够识别的“隐性特性”,还取决于我们对业务的深度理解。比如水杯的容量是否足够,要考虑水杯设计时面向的用户群体。茶杯、白酒杯、红酒杯、啤酒杯,它们的容量要求都是不一样的,我们不会希望一个白酒杯的容量能有 500ml。所以,在列举输入域时,一定要结合业务特性和用户群体。

回到之前的问题,接口要怎么测试?我们同样从与接口的交互考虑:我们可以发起接口调用,检查它返回内容的正确性;可以以相同参数反复请求,检查它的幂等性;可以高频次的发起,检查它的性能;可以尝试提交未经授权的请求,检查它的安全性等等。

 Python自动化测试学习交流群:全套自动化测试面试简历学习资料获取点击链接加入群聊【python自动化测试交流】:http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=DhOSZDNS-qzT5QKbFQMsfJ7DsrFfKpOF&authKey=eBt%2BF%2FBK81lVLcsLKaFqnvDAVA8IdNsGC7J0YV73w8V%2FJpdbby66r7vJ1rsPIifg&noverify=0&group_code=198408628

                  

 

2、用例的本质

在做完交互分析之后,会面临一个问题:在绝大部分(99.999..%)的情况下,输入域是无限的。比如,水杯中盛装的物品,可能是水、酒、可乐、饼干、草莓、浓酼酸...... (谁说只能装可饮用的液体?)我们穷尽一生,也不可能去尝试所有的输入。因此,业内才有一句话叫做:完美的测试是不可能的。那是不是代表测试就是在碰运气呢?并不然。

之所以测试领域会有这么多的用例设计方法论,原因就是我们需要把无限的输入域,变成有限的、有代表性的输入集。测试的意义,不是找到全部的缺陷,而是找到对业务有价值的缺陷。比如一款定位是面向下沉市场的水杯,杯子不够耐摔,就是有价值的缺陷,而杯体不够透明,就是无价值(或低价值)的缺陷。对任何一款产品或一块业务而言,我们都得把握好质量本身的“度”。

好的用例设计,是能够以尽可能少的用例,找到尽可能多的有价值问题。因此,用例的本质,是对问题的抽象,而测试人员最核心的能力,是对问题的定义和抽象能力。我们再来回顾这个公式:交互分析->等价划分->边界测试->用例组合,它其实就是一个 问题定义->问题抽象->问题简化->问题处理 的过程。

1)等价划分 是将输入域按某个维度进行的有效归并。比如可乐、雪碧、芬达,它们对于常规的水杯而言,都是同类物体,穷举测试并没有意义,我们可以把它们归为一类“碳酸饮料”。再比如,一个塑料杯,对于温度 10 度的可乐和 28 度的水,也没有分别,我们也可以把它们归为一类“常温液体”。注意这里在归类之后,会有输入重叠的现象,比如常温下的碳酸饮料,这个稍后很快会讲到。

2)边界测试 是提取单个输入域分类的有效代表值。对于单个输入域分类而言,可选的输入值仍然是无限多的,所以我们需要找到能够代表其他输入值的单值。而边界值往往就极具代表性。比如,对于水杯能够承受的液体温度,会有一个规定的上下限,而我们需要验证它是否能够真正达到这个限制(我们不会希望看到倒入开水之后杯子就爆开吧)。除了边界值外,还可以在非边界范围内随机挑选几个值做为代表。

3)用例组合 则是对这些代表值按分类做交叉考虑。像判定表、因果图、正交实验等,就是告诉我们如何做交叉考虑的方法论。前面提到的输入域重叠,即是不同分类的交叉点。比如,常温下的碳酸饮料、常温下的水、冰冻的碳酸饮料、冰冻的水、沸腾的碳酸饮料、沸腾的水......

很多测试教程,将等价划分和因果图等做为同一个维度的测试方法放在一块介绍,对测试新手会造成很大的干扰,以为它们相互并行,这其实是不正确的理解。前者是对问题的抽象,后者是对问题的处理。还有一个常见误区是,等价划分、边界测试仅用于黑盒测试,覆盖率分析仅用于白盒测试,这也是由于没有真正理解测试方法论造成的。比如对于如下代码:

if (value >= 1 && value <= 10) {
    System.out.println("I have " + value + " cards." );
}

等价划分和边界测试在这里仍然有用:20 和 30 是同一类,-5 和 -10 是同一类;0、1、2、9、10、11 就是它们的边界。同样,对于黑盒测试,也可以应用覆盖率分析,这就涉及到接下来的内容:业务建模和图论。

3、业务建模

先来看一个常见场景:登录。按照最粗略的设计,它可能会是这个样子:

当然,在真实情况下往往不会这么简单,比如忘记密码需要重置、在多次错误输入的情况下账号会被锁定等等。所以我们把场景中的红色部分做进一步的拓展:

注意这里其实并没有往流程中注入更多的东西,只是把“登录成功”和“登录失败”这两个部分(见虚线框)做了展开描述。然后,假设“校验通过”这个判断步骤的代码如下:

if (uname == null || pwd == null) {
  return errorResult("账号名或密码不能为空");
}
UserDO user = userMapper.getUserByName(uname);
if (user.getPwd.equals(encry(password))) {
  return succResult("登录成功");
} else {
  return errorResult("登录失败");
}

可以将它转化为等同的图形(因为篇幅的关系,登录成功和失败的细节重新被折叠):

这个例子阐明了一件事情:为什么上篇文章里说,像等价划分、边界测试、覆盖率分析等常见的用例设计策略,不能说它只适用于黑盒或白盒,在绝大部分情况下(确实也存在少数特定方法),黑盒、灰盒、白盒只是分解程度上的不同,它们可以通用、甚至混用。比如上图就是将黑盒部分和白盒部分混合在一起。

整个业务系统,都可以按照这种方式进行不同程度的拆解。拆解的目的,是为了得到输入点、输出点以及它们之间的可能路径。所有输入点的可选项,就是输入域;所有输出点的可选项,就是输出域,而输入点到输出点之间走过的路径的重复度(覆盖率分析),就是等价划分的依据。因此,拆解的粒度越细,能够识别的(子)节点和(子)路径越多,获得的输入域和输出域也就越完整,进行的等价划分也就越精确。

   Python自动化测试学习交流群:全套自动化测试面试简历学习资料获取点击链接加入群聊【python自动化测试交流】:http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=DhOSZDNS-qzT5QKbFQMsfJ7DsrFfKpOF&authKey=eBt%2BF%2FBK81lVLcsLKaFqnvDAVA8IdNsGC7J0YV73w8V%2FJpdbby66r7vJ1rsPIifg&noverify=0&group_code=198408628

 

这个拆解的过程,我们就叫做业务建模。它核心依赖两张图:业务流程图数据流程图。以一个简化过的购物下单流程为例,两张图分别如下(因画图工具的限制,图形的样式不专业,但不影响对内容的说明):

业务流程图比较好理解,即前面所说的路径,那为什么还需要一张数据流程图呢。原因是第一张流程图中存在隐蔽的“陷阱”:当我们新发起一个订单支付和支付失败需要重新支付时,虽然在流程图里的节点看起来是同一个,但实际上二者不是等价的(订单状态不一样,流水记录也不一样),所以“严谨”一点说,完整的流程图应该是这样:

由此可以看出,数据流程图对测试人员来说,有比较重要的“校验意义”,它可以帮助我们确认每个步骤产生的结果的正确性和完整性。

此外,它还可以做为模块化测试的依据:我们可以从庞大、复杂的业务流中,选择一部分节点和路径,做为一个模块。只要保证输入点的所有数据状态一致,就可以认为每次测试都是“幂等”的,它所到达的输出点的数据状态也应该与预期一致。由此,将复杂的业务系统隔离成一个个小的子系统,降低整体测试的复杂度。

那么,我们又该如何确认测试的完整性?假设有一个逻辑复杂的业务模块,它的流程图(实线部分)如下:

这时添加一条从结束点到开始点的路径(虚线部分),这张图就变成了一张有向环图(比如红色部分就是一个环)。从开始点到结束点的路径分支数,就等同于有向图的圈数。使用图论中的公式:V(G) = E - N + P(V 代表圈复杂度,E 代表边数,N 代表节点数,P 代表连通组件数(因为上图所有节点都是连通的,所以 P 为 1)),计算出圈数 = 13 - 8 + 1 = 6。即如果我们想要尝试所有的路径分支,至少需要 6 个测试用例,感兴趣的小伙伴可以自行数一数。在这张图中,边数最少的路径,我们一般将它做为关键路径(主路径),其他路径做为次要路径(辅路径)。边数越少,说明路径越重要,据此可以做为用例等级判断的依据。

更多测试相关的图论知识,推荐阅读机械工业出版社的《软件测试:一个软件工艺师的方法》(【美】保罗 C.乔根森(Paul C.Jorgensen) 著)。

4、其他一些测试法

除了以上讲解的“理性”的测试方法,还有一些“感性”的测试方法,同样可以给测试人员带来较大的帮助,最后我就选择部分常见的方法做个介绍。

角色分析法

角色分析法,是将自己作为目标用户来思考:如果我是用户,会以什么样的方式来使用产品。我们可以将用户划分为不同的角色,并构建出这些角色的使用场景,最终转化为测试用例。该方法的的作用是“以终为始”,跳出自身的视角限制,来发现用例设计中的盲点。

错误推断法

错误推断法,是根据测试人员的经验和直觉,列举出可能会出现问题的情况。我们可以在类似头脑风暴或用例评审的场合中,使用它来收集群体的想法。它非常依赖使用者的感觉,因此只能做为常规用例设计方法的补充,或在紧急的情况下采用,而不应将它做为主要的用例设计方法。

历史经验法

错误的发生往往会有一些“惯性”,所以在测试时,可以回顾一下过去在相同模块(或领域)发生过的问题,对它进行重复校验,也许会有“意外惊喜”。同样,当出现测试遗漏时,一定要及时补充我们的测试用例库,以免跌倒在同一个坑里。

现场验证法

测试人员设计出的用例通常是一种“测试数据”,我们很难确保它们能够覆盖到全部真实的数据情况。所以会采用一些方法来验证待发布产品在实际场景下的表现,比如预发测试、灰度测试、流量回放等等。

探索性测试

探索性测试严格上说不是一种测试技术,只是一种测试风格,它可以包含以上列出或未列出的各种测试方法。每次在探索性测试开始之前,可以定好这次测试的“主题”,或干脆就“自由发挥”,来增加发现深层缺陷的机会。这种方法如果结合众测,会有很好的效果。

总结:

感谢每一个认真阅读我文章的人!!!

我个人整理了我这几年软件测试生涯整理的一些技术资料,包含:电子书,简历模块,各种工作模板,面试宝典,自学项目等。欢迎大家点击下方名片免费领取,千万不要错过哦。

                                                                   

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/643261.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

华为OD机试真题 JavaScript 实现【矩阵稀疏扫描】【2023 B卷 100分】,附详细解题思路

一、题目描述 如果矩阵中的许多系数都为零&#xff0c;那么该矩阵就是稀疏的。对稀疏现象有兴趣是因为它的开发可以带来巨大的计算节省&#xff0c;并且在许多大的实践中都会出现矩阵稀疏的问题。 给定一个矩阵&#xff0c;现在需要逐行和逐列地扫描矩阵&#xff0c;如果某一…

备战金九银十,互联网大厂最全“Java 面试宝典 +Java 核心知识集”汇总

搬砖也有好几年了&#xff0c;本想在金三银四跳槽来着&#xff0c;结果我想你们应该猜到了&#xff0c;于是计划着下半年跳槽试试&#xff0c;算是提前为金九银十做准备吧&#xff01; 现在着手准备着以防万一自己措手不及&#xff0c;这不&#xff0c;这几天刚整理出炉的两份…

强化学习笔记-11 Off-policy Methods with Approximation

前几章我们讨论了off-policy方式&#xff0c;其同on-policy方式最大的不同之处在于其在训练所采取的动作&#xff0c;是根据behavior policy进行决策的&#xff0c;而不是根据target policy。这种方式的好处在于兼顾了exploitation and exploration。本节将讨论如何通过模型近似…

Spring MVC 的创建连接和使用

目录 前言&#xff1a; MVC 是什么&#xff1f; 1. Spring MVC 项目的创建和连接&#xff1a; 1.1 创建 1.2 连接 2. RequestMapping 注解使用详析&#xff1a; 2.1 指定请求类型&#xff1a; 2.1.1 指定 GET 请求 2.1.2 指定 POST 请求 3. 参数的获取与传递&#xff1a; 3.1 传…

CTR预估之WideDeep系列模型:DeepFM/DCN

前言 在CTR预估中&#xff0c;FM系列模型使用浅层网络&#xff08;线性模型&#xff09;&#xff0c;让模型自己学习特征组合交互&#xff0c;为显式建模的方式&#xff1b;而DNN系列模型使用深层网络&#xff0c;隐式挖掘模型的高阶特征交互。 本文继续介绍结合这两者优点的…

在我电脑中待了很久的5款使用办公软件

你电脑中用的最久的软件是哪些&#xff1f;以下是否有你曾经使用过的软件呢&#xff1f;工欲善其事&#xff0c;必先利其器&#xff0c;今天继续分享五款实用的办公软件。 矢量图绘制——Inkscape Inkscape是一款用于绘制和编辑矢量图形的工具。它可以让你用简单的操作来创建…

AI学术交流——“人工智能”和“神经网络学习”

作者简介&#xff1a;一名云计算网络运维人员、每天分享网络与运维的技术与干货。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;网络豆的主页​​​​​ 目录 前言 一.人工智能 1.“人工智能之父” 2.达特茅斯会议&#xff08;人工智能起源&a…

2023四大服装管理软件,第1款最受欢迎!

对于服装行业来说&#xff0c;依靠传统的方式管理服装门店或工厂&#xff0c;很难实现精准高效的管理&#xff0c;往往是耗费了大量的时间和精力&#xff0c;也没有挣到什么钱。 这就需要借助服装管理软件&#xff0c;来降低管理和运营的成本&#xff0c;减少工作量的同时&…

自带海量设计模板的网站 精准尺寸一键套用出图

现在大家通过手机去购物时都是通过查看商品的详情页&#xff0c;因为详情页会介绍产品的功能和产品的设计优势等&#xff0c;还有产品的基本信息。那么对于刚接触电商的商家来讲&#xff0c;制作详情页和商品主图是一件困难的事情&#xff0c;但如果套用模板或者是直接选择一个…

vue结合elementui表格el-table实现弹窗checkbox自定义列显示隐藏,刷新保持上次勾选不丢失,附完整代码

el-table实现自定义列显示隐藏 有时候表格太多列,要是默认全都显示就会很拥挤,又不能固定只显示某些列,这时候我们可以让用户自定义要显示隐藏哪些列。 网上很多教程都是用的v-if,但是v-if非常麻烦,每一列都要写判断条件,本篇文章将用动态渲染的方式来控制表格列的显示隐…

【Linux】perf使用和FrameGraph

本文主要说明perf和FrameGraph的使用&#xff0c;例如&#xff1a;火焰图的输出&#xff0c;系统性能状态查看等。 Author:mayimin perf version 3.10.0-1160.80.1.el7.x86_64.debug 参考资料&#xff1a;perf example&#xff1a; https://www.brendangregg.com/perf.html 一…

100天精通Golang(基础入门篇)——第7天:深入学习键盘输入和打印输出,掌握常用函数和包

&#x1f337; 博主 libin9iOak带您 Go to Golang Language.✨ &#x1f984; 个人主页——libin9iOak的博客&#x1f390; &#x1f433; 《面试题大全》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &#x1f30a; 《I…

【UE】滑动UI

效果 步骤 1. 新建一个控件蓝图&#xff0c;这里命名为“WBP_Slide” 2. 在关卡蓝图添加如下节点来显示控件蓝图 3. 打开“WBP_Slide”&#xff0c;添加一个滚动框控件 设置滚动框的锚点 设置滚动朝向为水平 在滚动框中添加一个画布面板 在画布面板中添加一个图像控件 由于我有…

设计优质微信小程序的实用指南!

微信小程序是一种快速发展的应用形式&#xff0c;设计良好的小程序能够提升用户体验并吸引更多的用户。在设计微信小程序时&#xff0c;有一些关键的指南可以帮助我们做出出色的设计。以下是即时设计总结的一些设计指南&#xff0c;希望能对准备设计微信小程序的人有所帮助。 …

64位和32位相比优势是什么(二)

程序的执行过程 当 CPU 执行程序的时候&#xff1a; 1.首先&#xff0c;CPU 读取 PC 指针指向的指令&#xff0c;将它导入指令寄存器。具体来说&#xff0c;完成读取指令这件事情有 3 个步骤&#xff1a; 步骤 1&#xff1a;CPU 的控制单元操作地址总线指定需要访问的内存地…

[CKA]考试之备份还原 etcd

由于最新的CKA考试改版&#xff0c;不允许存储书签&#xff0c;本博客致力怎么一步步从官网把答案找到&#xff0c;如何修改把题做对&#xff0c;下面开始我们的 CKA之旅 题目为&#xff1a; Task 首先&#xff0c;为运行在https://127.0.0.1:2379上的现有 etcd 实例创建快照…

36 # 加载 json 的处理流程

require 源码大致过程 mod.require 会默认调用 require 语法Module.prototype.require 模块的原型上有 require 方法Module._load 调用模块的加载方法&#xff0c;最终返回的是 module.exportsModule._resolveFilename 解析文件名&#xff0c;将文件名变成绝对路径&#xff0c…

UTF是变长编码

在阅读关于UTF8变长编码的文档时&#xff0c;看到如下内容&#xff0c; 文档中1110表示涉及3个字节&#xff0c;10表示涉及一个字节&#xff0c;还有后面的1110高位有三个1&#xff0c;表示从当前字节起有3字节参与表示UNICODE&#xff0c;后面的高位有1个1&#xff0c;表示从当…

Netty实战(十六)

UDP广播事件&#xff08;二&#xff09;编写广播者和监视器 一、编写广播者二、编写监视器三、运行 LogEventBroadcaster 和 LogEventMonitor 一、编写广播者 Netty 提供了大量的类来支持 UDP 应用程序的编写。下面我们列出一些要用到的类型&#xff1a; 名 称描 述interface…

价格·歧视

一级价格歧视与耳机价格歧视 价格歧视指的是厂商对于两个完全一样的产品收取不同的价格&#xff0c;无论是对同一消费者还是对不同消费者。 一级价格歧视&#xff08;完全价格歧视&#xff09; 对于每一个消费者都收取不同的价格&#xff0c;而且价格定在消费者最多愿意支付的…