如何评估测试用例有效性

2020-12-15 09:58:19 浏览数 (1)

每一个测试人都经历过测试用例评审,但是如何评估测试用例的有效性呢? 是不是我按照黑盒测试用例的设计原则来设计,这个测试用例就是一个有效的测试用例呢?(黑盒测试用例设计方法有:等价类划分法、边界值分析法、错误推测法、因果图法、判定表驱动法、正交试验设计法、功能图法、场景图法)。

我想答案是否定的,测试用例的有效性,更像是个玄学,长期以来,并没有一个相对科学的办法来验证。

下面这篇文章是原蚂蚁金服-义理大佬的一些实践,给我非常大启发,分享给大家。

01

为什么要评估测试用例有效性

想想你的团队有没有碰见过这样的问题:

1. 这么多的Case,花了大量时间和资源去运行,真的能发现Bug吗?

2. CI做到90%的行覆盖率了,能发现问题吗?

3. 测试用例越来越多,删除一些,会不会就发现不了问题了?

4. 怎么找出那些为了覆盖而覆盖,但是发现不了真正问题的测试用例?

想想上面的问题,再扪心自问:测试用例的有效性要不要评估?

测试用例有效性

要评估测试用例的有效性,首先要看,什么样的测试用例是有效的?

测试用例有效性

要评估测试用例的有效性,首先要看,什么样的测试用例是有效的?

测试用例有两个比较关键的部分:

1)调用被测代码:例如下面的RuleService.getLastRuleByClientId(ClientId)

2)进行结果Check:例如下面的AssertEqual(OrderId,"ABCD1234")

那么,测试用例具备不具备有效性,主要看以下指标:

  • 这个测试用例不仅能够“触发被测代码的各种分支”还能够做好结果校验。
  • 当业务代码出现问题的时候,测试用例可以发现这个问题,我们就认为这一组测试用例是有效的。
  • 当业务代码出现问题的时候,测试用例没能发现这个问题,我们就认为这一组测试用例是无效的。

由此引出测试用例有效性的理论建模:

测试有效性 = 被发现的问题数 / 出现问题的总数。

02

测试用例有效性评估度量方法

从运行时、非运行时, 正向和逆向这个维度, 我们可以得出以下的度量方式:

正向的链路扫描和静态扫描都比较常见,这里重点介绍下逆向的方式:

代码注入:

属于非运行时度量方式。通过向代码注入变异,来看测试用例是否能够发现问题。

内存注入:

属于运行时度量方式。也叫“”故障注入“”, 指在运行时进行操作和修改,来检查你的测试用例是否能反映出这个问题。 常见的有对API调用的返回结果进行修改,如果更改后,测试用例执行报错,则说明测试用例有效,反之说明无效。

这里重点讲下代码注入。

代码注入的原理是变异测试(mutation testing)。

变异测试的例子 我们用了一组测试用例(3个),去测试一个判断分支。 而为了证明这一组测试用例的有效性,我们向业务代码中注入变异。我们把b<100的条件改成了b<=100。 我们认为:一组Success的测试用例,在其被测对象发生变化后(注入变异后),应该至少有一个失败。如果这组测试用例仍然全部Success,则这组测试用例的有效性不足。

通过变异测试的方式:让注入变异后的业务代码作为“测试用例”,来测试“测试代码”。

那么可选的变异有哪些呢?

1. 线上的故障总结。

根据线上出现过的故障,总结其故障模式,然后将归纳后的符合故障模式的代码变异注入,以期望未来线上不会有同样问题出现。比如,代码中把空判断删除、更改日期格式(冬令时改成夏令时)、把相似函数混淆(例如把函数encodeing改成decoding)甚至发大程序中的数据范围(把金额从放大10倍或100倍)来引发错误。

2. 解决未知的问题。

上面的部分是已知的问题,那么还有很多我不知道有哪些问题的问题,这些问题怎么解决呢?

对于此类问题,可以寻找其通用解。

例如基于Java语言,把它的运算符,代码结构这一类的约定俗成的编码规范进行修改,例如把 改成-, 把=改成!=。

在此基础上,可以实现多种规则,主动的注入下面这些变异:

上面的介绍是理论,每个团队都可以看,可以学。下面的是蚂蚁金服的实践方案,大家可以按需参考

03

代码注入工程化方案

为了全自动的进行测试有效性评估,我们做了一个变异机器人,其主要运作是:

  1. 往被测代码中写入一个BUG(即:变异)
  2. 执行测试
  3. 把测试结果和无变异时的测试结果做比对,判断是否有新的用例失败
  4. 重复1-3若干次,每次注入一个不同的Bug
  5. 统计该系统的“测试有效性”

变异机器人的优点:

  1. 防错上线:变异是单独拉代码分支,且该代码分支永远不会上线,不影响生产。
  2. 全自动:只需要给出系统代码的git地址,即可进行评估,得到改进报告。
  3. 高效:数小时即可完成一个系统的测试有效性评估。
  4. 扩展性:该模式可以支持JAVA以及JAVA以外的多种语系。
  5. 适用性:该方法不仅适用于单元测试,还适用于其他自动化测试,例如接口测试、功能测试、集成测试。

变异机器人的使用门槛:

  1. 测试成功率:只会选择通过率100%的测试用例,所对应的业务代码做变异注入。
  2. 测试覆盖率:只会注入被测试代码覆盖的业务代码,测试覆盖率越高,评估越准确。

检查的结果如下:

04

持续优化

在执行的过程中,会碰见如下的问题:

那么还有什么方式可以持续优化呢?

<分钟级的系统评估效率>

为了保证评估的准确性,100个变异将会执行全量用例100遍,每次执行时间长是一大痛点。

高配版变异机器人给出的解法:

  1. 并行注入:基于代码覆盖率,识别UT之间的代码覆盖依赖关系,将独立的变异合并到一次自动化测试中。
  2. 热部署:基于字节码做更新,减少变异和部署的过程。
  3. 精准测试:基于UT代码覆盖信息,只运行和本次变异相关的UT(该方法不仅适用于UT,还适用于其他自动化测试,例如接口测试、功能测试、集成测试)

<学习型注入经验库>

为了避免“杀虫剂”效应,注入规则需要不断的完善。

高配版变异机器人给出的解法:故障学习,基于故障学习算法,不断学习历史的代码BUG,并转化为注入经验。可学习型经验库目前覆盖蚂蚁金服的代码库,明年会覆盖开源社区。

<兼容不稳定环境>

集成测试环境会存在一定的不稳定,难以判断用例失败是因为“发现了变异”还是“环境出了问题”,导致测试有效性评估存在误差。

高配版变异机器人给出的解法:

  1. 高频跑:同样的变异跑10次,对多次结果进行统计分析,减少环境问题引起的偶发性问题。
  2. 环境问题自动定位:接入附属的日志服务,它会基于用例日志/系统错误日志构建的异常场景,自动学习“因环境问题导致的用例失败”,准确区分出用例是否发现变异。

05

最终我们要实现这样的目标:

测试从 代码都能跑-->代码都被测试到了-->代码都测试好了。

最后放一个测试度量三板斧:

如果大家对本演讲的原视频感兴趣,可以通过此观看:

https://www.itdks.com/Course/detail?id=117569

0 人点赞