一、 为什么要做用例精简和精准测试
1、 测试用例越来越多,测试效率低下
这是因为在目前的快速迭代开发模式下,测试人员需要不停覆盖不断调整的产品逻辑需求,因此测试用例也越来越庞大了,以病毒查杀为例,目前用例已达500多条用例,导致全量测试时间很长,同时发现的问题并不和用例数成正比
2、 以往迭代测试用例更多是功能“点”的覆盖,而不是用户场景“线”、“面”的覆盖
目前产品经理给出的需求都是增量文档,也就是很难有某个产品的完整需求文档,因此,每次用例更多是功能点的覆盖,比如需求文档里面提到点击某个按钮会有什么变化,那某次用例编写时可能只是简单的覆盖,但这种用例并不完全符合用户实际场景,因此还是可能出现覆盖不完全问题。
3、 用例精简是精准测试的基础之一
精准测试的本质是在有代码变更时可以快速并精确地挑选出所影响的用例,在不影响质量的同时降低工作成本,理论上精准测试已经可以提高工作效率,但如果同时再加上精简后的用例,那就可以在精准测试的基础上再次降低工作成本。
因此用例精简可以是精准测试的基础之一。
4、 用例精简降低用例执行的多次投入成本
测试中的成本按其时间跨度可以分为:单次投入成本和多次投入成本。例如:编写测试用例可以看作是单次投入成本,因为编写测试用例一般是在测试的计划阶段进行(Scrum每个Sprint的开始阶段)的,虽然后期会有小的改动,但绝大多数是在一开始的设计阶段就基本上成型了;测试用例(包括:手工和自动化测试用例)的执行则是多次投入成本,因为每出一个新版本Build时都要执行所有的测试用例。
因此,我们虽然增加了用例精简的单次投入成本,但总体降低了后续用例执行时的多次投入成本降低。
二、 用例精简原则概要
用例精简本质是,用更少的用例发现相同或更多的问题。因此,精简原则重点是:
从用户场景出发,合并、删除功能点用例,从“线”、“面”整体考虑用户场景,对已有用例进行精简和重构。
首先,先筛选出正常跟异常用例。异常用例是对测试的补充,也是探索性测试在用例方面的表现,所以对异常类的用例精简应跟正常用例进行结合,这部分下面会提到精简方案:
场景原则精简用例:
假如有一个功能A,有三个子功能A1,A2。A2的测试路径基于A1的功能操作,那么就用TestA1_A2来贯穿这个测试用例。每一个测试动作都是一个点,但是把这些测试要点结合起来连成一条线,甚至是面的覆盖,这就是一个测试场景。测试场景可以覆盖的面是比较广的,也可以较好的模范用户操作行为。
对需求的理解精简用例:
在最开始的时候,我们写用例都是根据需求文档的内容进行场景划分,用例编写。当需求越来越完善的时候,我们需要及时地精简我们的用例,明确需求是什么,场景是什么。将需求转化为对用户场景的模拟,实际的去重构用例。例如:第一阶段:当产品出了需求,有AB两个模块,A能调用起B模块。这个时候用例可能就关注功能需求,A调用B。第二阶段,需求二:加入C模块,A模块能调用起C模块;第三阶段,加入D模块,A能调用起D模块...。这个时候我们要关注的不再是需求功能,而是转化为对需求的理解:A模块能够成功调用其他模块的所有内容。
对比手段精简用例:
一开始我们把用例分为异常类型跟正常类型的用例之后,就是为了在对比测试这里用到。假如正常类型用例A,异常类型用例A+,当我们把执行顺序是TestA+, A的时候,就是一种对比类型的精简用例方法。
合并、降低缺陷出现率低的用例优先级原则:
按照无线的测试指南,正常逻辑的用例应该标为一级用例,同时占比不超过30%,但是在实际测试工作中我们可能需要再进行细化优先级,比如病毒查杀有500多条用例,那么理论上一级用例就多于150条。如果把这150条作为上线前测试的话,一个下午光做病毒模块的上线前都没法做完。
同时,虽然一级用例都是正常逻辑,但是从测试数据、用户反馈数据来看,功能模块的缺陷可能只集中在几个场景中,因此我们需要重视这几个场景,把相关的用例精简重构作为上线前用例,合并或降低缺陷出现率低的一级用例。
补充用户反馈跟缺陷的bug补充用例:
软件开发中有个80:20的原则,80%的效果是由20%的原因导致的,或者是80%的结果来自于20%的努力。同理,80%的缺陷主要集中在20%的代码中,90%的停机是由10%(甚至更少)的缺陷造成的。
所以,注重用户反馈,注重缺陷的场景,显得特别的重要。这部分看起来虽然不在精简范围内,但是这部分却应该是在用例设计补充里面。精简的用例要能做到很好的覆盖,有更好的效果,就需要重视缺陷的集中地带。同时用户真实的场景跟需求的场景也是可以在这里得到反映。
三、 用例精简实践
根据上面的几个原则,我们抽取了广告拦截模块用例进行精简实践。首先我们先对以往缺陷的集中点进行了梳理,随后按照以上几个原则进行了精简和重构:
精简效果反馈:
力度:精简前的用例数据达到了223条用例,经过精简之后,目前用例数目只剩150条用例,减少了73条用例。
时间:73条用例一般需要1天/人去执行,这对效率上面是有很大提升。
四、 用例精简效果粗略验证
这里只提到粗略验证,是因为我们认为用例精简有效果验证有两种方式:功能点检查和全量覆盖率结果,功能点的完善性可以通过内部和外部评审实现,但比较耗时,也可以通过标注新旧用例之间的对应关系来确保精简后用例覆盖的功能点不遗漏。
全量覆盖率验证,主要是使用同一个版本测试包对精简前后用例进行覆盖率测试。目前覆盖率测试有行覆盖、方法覆盖、块覆盖,行覆盖率相对方法覆盖精度比较高,虽然不能百分之百的精确,但已经可以作为基础的衡量标准,因此我们抽取了部分精简后的用例进行覆盖率测试。
五、 精准测试方案和实践
上面提到用例精简是精准测试的基础之一,因此在用例精简之后我们也做了精准测试的实践。
精准测试的本质是,代码有变更时用更少的用例去覆盖变更涉及的功能点,以达到提高测试效率的目的。
代码变更到用例挑选,这就很自然地引出一个问题,那就是代码变更时如何快速找到相应的测试用例,目前解决这问题的思路有两种,一种是通过阅读代码从而梳理出软件架构,这种方式的输出是代码文件和功能逻辑的对应关系,当代码有变更时找到对应功能逻辑从而挑选出需要执行的用例,这种思路是一次投入长期收益,但比较耗时,而且要求测试同学的代码功底比较强,同时需要开发同学的帮忙;另一种是执行某个功能模块用例集时输出代码日志,从代码日志里面也可以找到功能模块的对应关系,这种方案对测试同学的代码能力要求不高,比较适合外包同学的执行,但也比较耗时,同时需要不停维护对应关系库。
同时,版本间的变更识别也有两种思路,一种是成都同学的查看SVN日志,再从日志详细代码中识别出变更逻辑,找到对应用例;还有一种是通过SVN diff,直接从版本间的SVN diff来获取代码变更;这两种方法的思路是想通的,都是利用SVN来找到版本间的差异,但是相比SVN日志,SVN diff结果没有那么直观,只看到差异部分,而且差异部分不一定能够看到前后代码,只有零散的增删改,没有整体概念,这是因为SVN diff结果只会对有增删改的代码往前追溯7行,比如以下变更代码就很难看出是在哪个功能点有变更:
我们的方案和以上两种思路不完全相同,但也采用SVN diff作为技术基础,需要对SVN diff结果再做处理,我们采用类似迭代的思路去逐步求精,也就是开始选择用例时是根据经验尽可能找到对应的用例集,在执行结束时根据此轮覆盖率情况再决定是否需要再挑选更小的用例集。这思路相比预先阅读全部代码和通过日志方案更敏捷,也无需对软件代码细节非常了解,如果结合开发同学的讲解,效率会更高,对架构理解更深。
在给出具体的实践之前,也插播下精准测试的背景:作为测试人员,在版本提测时你是否也会经常收到开发这样的信息,那就是开发人员说某个功能没什么大改动,简单过下就好了,但是就这么一句话测试人员可能就要忙半天了,具体改啥了?“简单过下”到什么程度?这些都是头痛的问题,比如广告拦截在手机管家5.1版本中有变更,开发的提测建议如下:
广告拦截除了第一点有涉及之外,其他变更内容都浓缩在第四点里面,对这样的一句话你放心吗?作为测试人员怀疑精神是要有的,因此我们要想既保证质量又不做无用功就得考虑精准测试了。
我们做了个比较粗糙展示系统,这系统可以实践我们“迭代的思路去逐步求精”想法:
1、 分析版本间变更内容
变更内容的基础是SVN diff,但是因为SVN diff原始结果不直观,因此我们需要对结果再进行解析处理,处理后可以在源码中用不同颜色标明变更内容,而不是直接的SVN diff结果。
初次结果报告覆盖率基本上为0:
2、 根据源码中的变更,判断大概变更涉及模块,挑选出此轮用例。
根据代码变更内容(快速的办法是找开发同学一起过下变更内容),我们可以得知5.1和5.0版本之间广告拦截主要有以下功能点变更:
1)监测到系统通知栏新消息
2)调用临时root失败
3)卸载安装包时清除通知栏消息;
4)启动通知栏监控;
5)获取广告行为表
6)修改广告软件配置
7)广告详情页面展示
8)广告页面刷新
由此可以看到通过查看变更代码可以了解到需要覆盖的测试点
3、 执行此轮用例,利用覆盖率执行结果ec文件再次生成用例执行覆盖情况。
4、 根据此轮用例执行覆盖率情况,再决定是否需要做下一轮的用例挑选。
根据以上粗略挑选用例,发现覆盖率仍比较偏低,因此通过查看具体代码再增加测试用例覆盖,逐步提高覆盖率:
5、 最终完成变更的覆盖,实现精准测试的目的。
最终逐步挑选出约50条用例覆这两个版本间的实际代码变更,不再盲目测试。由于变更代码中有大概10%的保护代码,因此90%的行覆盖率已经比较理想了。同时,由于测试人员逐步分析变更代码,也使得大家对广告拦截的代码逻辑更清晰,增加了发布质量的信心。