精准化测试,实际上就是对「业务」——「测试用例」——「代码」进行关联建模并追踪他们的变化。

背景

测试过程中,经常会遇到这样的问题:

我自测过了,你简单测下就好了。

代码重构了,我也不知道影响什么业务……

我就升级了SDK,不知道有什么影响……

代码改动挺多的,要么全测一遍吧!

我就改了一行代码,你要测几天?

这就是当前敏捷开发模式下,测试和开发的矛盾会越来越多的原因。快速的迭代,会极大的扩大测试的回归成本。

所以,敏捷开发下测试的最终选择,一定只有两条路:

  • 自动化测试,降低人工成本
  • 缩小回归范围,提高测试效率

否则大量的回归测试内容,会给测试团队增加数倍的工作量。

而它们的优先级,一定是优先「缩小回归范围」,自动化测试只是工具,缩小回归范围,才能给团队带来效率的提升,这个方向就是通过「代码分析」,来找到缩减无关的测试内容。

例如一个线上问题,对指定机型的设备有bug,开发进行修复后,对指定机型进行了if else判断,测试用例可以缩减到当前判断分别为true和false的场景。

敏捷开发模式下,唯一不变的是「变化」,测试分析,就是从变化中找到核心的影响因素,分析出应该测什么,不用测什么。

那么在这样一个环境下,我们怎么来保证,我「提交的代码」、「测过的Case」在任何时候都是正确的呢?

当你无法量化的时候,你就在用你的人品和信誉做担保,而开发团队对你的信任也是基于你的信誉。可是在你还没有建立你的信誉的时候,你就必须拿出量化的东西来赢得信任。

精细化测试,需要测试从提交的代码中找到具体的业务修改点,这对测试的要求很高,一般来说,可以和开发共同完成,但是很多情况下,开发的一个commit,有时候并不是很纯粹,经常会夹带一些「私货」,这也是引起测试未覆盖的一个重要原因。

设计思路

针对上面的这些问题,在开发的角度,我们希望能对测试的效率进行提升。

技术选型

在服务端开发中,通常使用「单测+覆盖率」的方式来保证代码的执行覆盖程度,所以,这里借助代码覆盖率,来作为关联代码和用例的桥梁。

日企单测跑覆盖率,大于95%才算合格的单测。

在移动端,代码覆盖率通常使用JaCoCo,即 Java Code Coverage来实现。

在实际开发过程中,一般不太会对全量代码做检测,所以,需要改造JaCoco,提供增量探针功能。

除此之外,还可以通过ASM来解析AST语法树,获得更加精准的探针定位,或者类似Lint和Findbugs增加自定义的解析规则。

创建测试用例库

测试用例库的建立,是映射代码和测试用例的基础,它有以下作用。

  • 在测试用例库中查找相应的代码映射关系
  • 获取推荐的测试用例集

一个测试用例的执行,在代码层面上来看,实际上就是一系列函数的调用链。在执行测试用例的时候,在函数调用链上记录下对应的关系即可。

关联代码函数调用链和测试用例

这一部分通常在代码提交时执行,开发提交代码后,会通过Gitlab或者其它工具来获取代码diff,并去除代码噪音(公共函数、重命名、空白、注释log等),根据用例库的关联,来筛选需要回归的用例。

精准化测试需要采集代码和用例之间的关系,根据代码变化的内容,推算出回归测试的范围。这一部分是整个架构的技术难点。

代码耦合,导致差异化被放大,从而导致代码分析被污染,无法缩减回归范围。

对推荐用例进行自动化或者手动测试

获取推荐用例后,可以进行自动化测试,或者是人工手动测试来对推荐用例进行回归。

甚至可以通过AI训练代码-用例模型,通过特征提取,完善用例推荐的智能程度。

精准化测试的作用

精准化测试对开发和测试的收益如下:

  • 将黑盒测试转化为白盒测试
  • 统计到行,提高了发现问题的精读和效率
  • 提升了测试回归用例的效率
  • 反向约束了代码规范

实际推进

整个精准化测试平台的搭建需要各方面的资源,建议分阶段来实现。

phase1

先解决提交的代码的覆盖率是否都完成了这件事。

这部分,我们需要利用JaCoco增量探针机制,对diff代码做扫描,用例测完后,导出覆盖率数据,看是否覆盖所有的修改代码。

需要做的工作

  • 修改JaCoco源码,支持增量探针
  • CI支持编译精准测试包,用例测完后自动上传覆盖率文件
  • 覆盖率文件解析平台搭建

phase2

搭建测试用例库,落实代码与覆盖率关联的映射关系。通过自动化测试和人工测试结合的方式来丰富和完善整个测试用例库。

对于自动化测试来说,可以通过在功能测试阶段试验录制脚本回放的方式获得映射关系。

phase3

从用例库中提取代码变更影响的用例。

phase4

与CI上的其它质量管控平台对接,单独创建覆盖率包。

使用SonarQube作为覆盖率与测试用例的分析平台

使用JaCoCo作为代码覆盖率的分析工具

使用JaCoCo-cl实现对单个用例的覆盖率收集

使用SonarQube-Scanner完成覆盖率导入

调整SonarQube平台中覆盖率展示的信息,加入关联测试用例的展示,方便在未覆盖的代码附近可以找到最接近的测试用例

phase5

解决多人测试协作的问题,实现单机覆盖率——联网覆盖率——实时覆盖率的演变。

参考

https://testerhome.com/topics/22329

https://blog.csdn.net/ByteDanceTech/article/details/117376918

纲要

这篇文章是整个系统开发的总览,后续会根据纲要中的技术知识点,一步步完成整个体系的建设。

主要涉及到的知识点如下:

  • JaCoco覆盖率原理探究
  • Gradle Plugin开发
  • 字节码探索之旅
  • ASM操作字节码的一般姿势
  • JaCoco增量覆盖率的改造
  • Coverage Report的生成
  • 增量Coverage与CI系统的对接

整个系列看完,你不仅可以收获一个增量覆盖率插件,更能顺便掌握高阶程序员的硬通货——使用Gradle插件与ASM的配合操作来操作字节码。

向大家推荐下我的网站 https://xuyisheng.top/ 专注 Android-Kotlin-Flutter 欢迎大家访问