Practical Regression Test Selection With Dynamic File Dependencies

摘要

提出一个新的,轻量级的回归测试选择(RTS)方法——EKSTAZI。这个方法跟踪文件相关测试上的动态依赖。在32个开源项目共615个版本上进行测试。结果显示EKSTAZI方法平均减少32%的测试时间,其中长时间运行的测试时间与全部测试相比减少了54%。

1. 介绍

已有研究表明回归测试可以最多减少80%的测试预算和最多50%的维护成本。

一个典型的RTS技术一般分为三个阶段:

  1. a n a l y s i s ( A ) \mathcal{analysis(A)} :选择要运行的测试
  2. e x e c u t i o n ( E ) \mathcal{execution(E)} :执行测试用例
  3. c o l l e c t i o n ( C ) \mathcal{collection(C)} :收集当前版本的信息以便分析下个版本

已有的评价RTS技术的指标基于选择的测试的数量: E \mathcal{E} 阶段的执行时间,有些只分析 A \mathcal{A} E \mathcal{E} 阶段的时间。

EKSTAZI基于文件依赖进行分析(本文之前给的例子貌似是基于系统进行回归测试,里面给的一个例子是YouTube依赖于Guava,所以当Guava中任何东西修改后,YouTube的所有测试都会跑,这是基于一个生态系统的回归测试)。之前的工作基于类依赖和外部资源依赖。EKSTAZI和刚刚提到的细粒度的RTS技术不同的是,它不依赖于和版本控制系统集成(version-control systems,VCS)。

EKSTAZI计算每个测试入口(测试方法或测试类)依赖于哪些文件,如果一个测试依赖的文件没有修改那么它就不用再新版本上执行。

最后在32个Java项目的615个版本上进行评价,这也是RTS研究中最大的实验。

2. 栗子

selection granularity(选择粒度):跟踪测试用例执行轨迹和测试用例选择的粒度

dependency granularity(依赖粒度):变更所影响的级别

EKSTAZI使用类作为依赖粒度,方法或类作为选择粒度

EKSTAZI的粒度选择导致它会最终选出更多的测试用例,即在 E \mathcal{E} 阶段时间开销更大,但是在 A \mathcal{A} C \mathcal{C} 阶段缩短了时间,所以端到端的时间更短。

3. 技术和实现

3.1 分析( A \mathcal{A} )阶段

对于每个测试实体,先检测所有文件的checksums是否变化(实际上还是要看文件是否变更)。

对于新增测试用例,如果没有依赖信息,那么全都加进去。

3.2 执行( E \mathcal{E} )阶段

两种方式:

  1. 紧集成:构建系统找到所有测试类然后调用测试框架进行测试,然后再进行 A \mathcal{A} 阶段确认每个测试实体是否需要运行。

QQ截图20190311131517.png

具体方法如图,one pass( A E C \mathcal{A}\mathcal{E}\mathcal{C}

  1. 松集成:首先确定某个测试实体要不要跑,把不要跑的搞一个excludes列表,然后跑测试用例,这样做可以减少运行开销。

QQ截图20190311131550.png

two pass,( A E \mathcal{A}\mathcal{E} )+( A E C \mathcal{A}\mathcal{E}\mathcal{C} ),这里第二个 E \mathcal{E} 是选择后的测试用例,减少了运行开销。

3.3 收集( C \mathcal{C} )阶段

这个阶段创建被执行测试实体的依赖文件。EKSTAZI监控测试的执行,收集测试代码在执行时经过的文件,保存他们相关的依赖文件,目前这个收集采取的策略是只要读或写都属于依赖。如果通过识别没有创建依赖的写操作会更精确。

收集文件依赖的工作可以使用工具FabricateMemoize。但是不是很精确,有以下两个原因:

  1. 当多个实体运行在JVM上时,不能收集到每个实体的依赖
  2. 不能收集到打包在.jar文件中的.class文件层面的依赖

EKSTAZI提供了API:

  1. entityStarted(String name):当进入某个测试实体时清空之前的依赖
  2. entityEnded(String name):在测试结束时保存所有收集到的依赖

插装的代码点

  1. 构造函数开始
  2. 静态生成器开始
  3. 静态方法开始
  4. 获取静态域
  5. 使用类文字(class literal)

不对对象实例的方法进行插桩,因为对象的方法调用前,类的构造方法肯定已经调用了,用来捕获类的依赖。

3.4 依赖格式

1552284959130

3.5 智能的checksums

使用checksums的优点:

  1. A \mathcal{A} 不用获取老版本源代码(老版本的checksum都已记录下来)
  2. 比较hash值能快

代价:

  1. A \mathcal{A} C \mathcal{C} 阶段需要比较checksum检查文件是否变更,增加了分析开销

3.6 集成到Junit中

4. 评价

32个项目的615个版本,总共4,937,189行源代码

short running:执行时间少于1分钟的测试套件(套件是啥呀。。所有测试用例还是某个测试类还是单个测试用例啊。。搜了一下参考材料似乎是所有测试用例)

4.3 结论

QQ截图20190311145313.png

最后选出来的测试实体比例为所有测试实体的5%38%,$\mathcal{A}\mathcal{E}\mathcal{C}$时间为runAll时间的9%138%,平均为68%, A E \mathcal{A}\mathcal{E} 为runAll时间的7%~99%,平均为53%。

4.4 智能的checksums

QQ截图20190311145801.png

8. 结论

主要介绍了EKSTAZI技术和实现。在开销上比state-of-the-art的工具更优。EKSTAZI已经集成到一些著名开源项目的主要仓库上,包括Apache Camel, Apache Commons Math和Apache CXF

猜你喜欢

转载自blog.csdn.net/u014578266/article/details/89057954