需求分析完了,测试范围界定好了,现在该设计测试用例了。问题来了:怎么设计出“好的”测试用例呢?
一、什么样算“好”
茹炳晟老师用鱼塘来距离我觉得很形象:
如果把被测试软件看作一个池塘,软件缺陷是池塘中的鱼,建立测试用例集的过程就像是在编织一张捕渔网。 “好的”测试用例集就是一张能够覆盖整个池塘的大渔网,只要池塘里有鱼,这个大渔网就一定能把鱼给捞上来。 如果渔网本身是完整的且合格的,那么捞不到鱼,就证明池塘中没有鱼,而渔网的好坏与池塘中是否有鱼无关。
所以说,“好的”测试用例一定是一个完备的集合,可以覆盖所有等价类以及各种边界值,而跟它最终是否可以发现缺陷无关。
二、“好”用例具备特征
1. 整体完备性
往往一个功能点需要涉及到多个用例去覆盖方方面面,所以测试用例是一个完备的整体,是有效测试用例的集合,能完全覆盖测试需求。
2. 准确地等价类划分
指的是对于每个等价类都能保证只要其中一个输入测试通过,其他输入也一定测试通过。
比如测试微信红包,0<金额<=200
是其中一个等价类,输入任意范围内的数字 都是可以通过的,说明这个等价类是准确的。
3. 等价类集合的完备性
需要保证所有可能的边界值和边界条件都已经正确识别。
还以上面红包为例,金额<=0
、金额>200
这2个属于无效等价类,0 和 200 就是边界值,这些都要确定清楚。
三、最常用三种用例设计方法
怎么是三种?明明网上和各种书籍上有好多种啊。
比如等价类划分法、边界值分析法、错误推测方法、因果图方法、判定表驱动分析法、正交实验设计方法、功能图分析方法、场景设计方法、形式化方法、扩展有限状态机方法等等。
但是,从实践角度来讲,真正具有实用价值并且常用的只有前三种方法:等价类划分法、边界值分析法、错误推测方法。
注意,这里并不是说其他方法没有用,在一些特定领域,有着几近变态的测试覆盖率要求,会采用更多的测试设计方法。只是对于大多数的软件测试而言,综合使用等价类划分、边界值分析和错误推测这三大类方法就足够了。
你想想自己是不是这样?
1. 等价类划分方法
等价类中任意一个输入数据对于揭露程序中潜在错误都具有同等效果。后续我们只要从每个等价类中任意选取一个值进行测试,就可以用少量具有代表性的测试输入取得较好的测试覆盖结果。
通常要考虑有效等价类和无效等价类。
比如,学生信息系统中有一个“考试成绩”的输入项,成绩的取值范围是 0~100 之间的整数,考试成绩及格的分数线是 60。
有效等价类 1:0~59 之间的任意整数 2:59~100 之间的任意整数 无效等价类 1:小于 0 的负数 2:大于 100 的整数 3:0~100 之间的任何浮点数 4:其他任意非数字字符
2. 边界值分析方法
边界值分析是对等价类划分的补充,你从实践经验中可以发现,大量的错误发生在输入输出的边界值上。
所以需要对边界值进行重点测试,通常选取正好等于、刚刚大于或刚刚小于边界的值作为测试数据。
继续看学生信息系统中“考试成绩”的例子,选取的边界值数据应该包括:-1,0,1,59,60,61,99,100,101。
3. 错误推测方法
错误推测方法是指基于对被测试软件系统设计的理解、过往经验以及个人直觉,推测出软件可能存在的缺陷,从而有针对性地设计测试用例的方法。
这个方法强调的是对被测试软件的需求理解以及设计实现的细节把握,当然还有个人的能力。缺点也显而易见,那就是难以系统化,并且过度依赖个人能力。
举例说说:
- Web 页面测试,需要考虑浏览器在有缓存和没有缓存下的表现
- Web API 测试,需要考虑被测 API 所依赖的第三方 API 出错下的处理逻辑
- 代码级单元测试,需要考虑被测函数的输入参数为空情况下的内部处理逻辑
这些测试用例的设计都是基于曾经遇到的问题而进行的错误推测,很大程度上取决于个人能力。
为了降低对个人能力的依赖,企业通常会建立常见缺陷知识库,在测试设计的过程中,会使用缺陷知识库作为检查点列表(checklist),去帮助优化补充测试用例的设计。
四、如何才能设计出“好的”测试用例?
这个就没有一个统一的套路了。
因为在真实的工程实践中,不同的软件项目在研发生命周期的各个阶段都会有不同的测试类型。比如单元测试、集成测试、GUI测试、API测试、中间件测试等等。对于不同类型的测试,设计测试用例的时候差异也会很大,有些可能采用黑盒方法,有些可能采用白盒方法,有些还会采用灰盒方法。
但是,有一点可以确定:
想要做好测试的分析,必须要深入理解需求。这也是为什么我们希望测试能在需求分析和设计阶段就开始介入的原因。
然后就是做好这 2 点:
- 从软件功能需求出发,全面地、无遗漏地识别出测试需求是至关重要的,这将直接关系到用例的测试覆盖率。
- 对于识别出的每个测试需求点,需要综合运用等价类划分、边界值分析和错误推测方法来全面地设计测试用例。
五、其他容易被忽略的“秘籍”
记得以前机票的一个测试大佬跟我提过,你千万不要一来就扎进具体业务里去。现在回想他的话,的确如此。
我们往往在接到具体需求后,就开始针对这个需求开展测试工作,但是对于整个架构理解甚少,这对我们是很不利的:
1. 切忌不能把整个被测系统看作一个大黑盒
必须对内部的架构有清楚的认识,比如数据库连接方式、数据库的读写分离、消息中间件 Kafka 的配置、缓存系统的层级分布、第三方系统的集成等。
2. 必须深入理解被测软件的设计与实现细节,深入理解软件内部的处理逻辑
单单根据测试需求点设计的用例,只能覆盖“表面”的一层,往往会覆盖不到内部的处理流程、分支处理,而没有覆盖到的部分就很可能出现缺陷遗漏。
3. 切忌不要以开发代码的实现为依据设计测试用例
因为开发代码实现的错误会导致测试用例也出错,所以你应该根据原始需求设计测试用例。
4. 引入需求覆盖率和代码覆盖率
引入需求覆盖率和代码覆盖率来衡量测试执行的完备性,并以此为依据来找出遗漏的测试点。需求覆盖率其实还好做,代码覆盖率可能得花点精力,后面再聊。