“代码变更覆盖率”在后端测试中的实践

 最近一直对测试覆盖率方面的内容比较感兴趣,虽然很多项目都早已经用上了Jacoco来实现测试覆盖率的统计,但是很少看到实际项目中基于覆盖率统计来指导测试的实践。这篇文章是我近期基于代码变更风险(CR)平台 (upload/201811131026161806.png" alt="" style="margin: 0px; padding: 0px; border: 0px; max-width: 900px; height: auto;" />

 
可以看到,在表格里没有出现GlobleAttribute.java(不知是否是因为该类只添加了一行常量定义,改动太小的缘故),而TriggerManager.java类的改动部分覆盖率为63.6%。点进去再仔细看下新修改的行的覆盖情况:
 
 
可以看到“新修改”的未覆盖部分(红色)主要是因为 if (t.getContext().containsKey(GlobleAttribute.AZ_BACKFILL_INSTANCES_NUM))判断没有命中,因为该需求引入了新的参数az.backfill.concurrent.num 指定补数据实例产生的并发度 。而该参数我们还并没有设置过。
此外,下面的未覆盖部分, if 判断的后半段 flow.getScheduleType().equals(ScheduleType.BACKFILL)未命中的原因是因为我们还并没有执行过补数据的调度。
 
4. 执行手工测试
对一个作业流设置补数据调度100次,指定补数据实例产生的并发度为5(设置参数az.backfill.concurrent.num 的值为5),验证补数据调度按照既定场景正确执行。
 
5. 测试结果
查数据库显示,补数据调度按照顺序执行, 但是实例个数始终为1。
显然,该需求的基本功能生效了(从以前的并发实例数不受限,现在实例个数为1),但是并发度参数并没有生效。
 
6. 结果分析排查
重新执行覆盖率统计,再来看一眼CR平台的新的结果:

 
可以看到,覆盖率有一定的提升。但是为什么并发参数设置没有生效呢? 来看一眼服务器上的执行日志,拉到日志的最后,看到有一条频繁打印的日志:“backfill trigger 3959, .......”:

 
再对照一下CR平台上变更的代码:

 
可以看到,下面这部分“新修改”的代码应该打印的日志还处于“未覆盖”的状态。往上看,发现红框中圈出的代码段里打印的日志刚好就是服务器上后台的日志。看一眼判断条件: 判断该作业流是否已经有执行实例正在执行中,且该正在执行中的作业流实例的开始时间距离现在不到10分钟  。
这样就初步解释了 目前阶段为什么我们没看到“新修改”日志打印,以及实例没有生成的直接原因。即: 被之前的判断条件错误拦截了。
等待10分钟,我们继续查看数据库的结果,发现并发的实例数仍为1。 再看一眼CR的覆盖情况:
 
 
可以看到,刚才未覆盖的这段日志打印,在10分钟过去后被执行了。为了确认该数据的准确性,再看一眼日志,这次我们直接搜索“Reach az.backfill.instances.num ......”这条日志:
 
可以看到,日志确实出现了变化。也就是说,服务器执行的代码进入了判断: “到达了补数据实例个数的上限 isReachBackfillInstanceNum(t)” 。
然而,我们设置的上限明明是5,为什么却显示已经达到上限,而数据库里的实际并发数还是1呢?
再看一眼,变更代码中未覆盖的变更行:
 
 
可以发现,在isReachBackfillInstanceNum(t)方法中,刚好找到了我们想要的内容:默认的补数据实例个数backfillInstancesNum为1,当调度t的上下文信息context中包含参数GlobalAttribute.AZ_BACKFILL_INSTANCES_NUM时,就用该对应的值赋值给backfillInstancesNum。且会对该范围进行1-100的判断。
而这段代码正好没有被执行。
再次进入源码查看,发现了个惊人的事情:
 
 
这个AZ_BACKFILL_INSTANCES_NUM参数的实际key值,应该是az.backfill. instances.num,而开发兄弟在需求和jira中写的都是“az.backfill. concurrent.num”。
此时,我的心情是复杂的。此处需要省略1000字。
如你所知,后续修改参数key后,重新测试,成功测试通过。通过后的覆盖率统计情况:
 
 
唯一没有覆盖的行,是因为设置的并发参数的值是5,在该1-100范围内,所以没有进入该判断。
 
例子二:
篇幅有限,再来简单介绍另外个利用CR平台完善测试的例子。
 
需求:
将执行节点的流实例并发数量的值写进db,在节点服务启动时,优先从db中读取加载进内存。如果db中不包含,再从配置文件读取。
简单测试后, 看下CR平台的覆盖情况:
 
 
可以看到,对于基本的正常功能,我们还是覆盖到了。 但是仍有大部分语句没有覆盖,而这部分未覆盖的内容其实就是查询数据库时发生异常情况。
知道未覆盖的原因,就好办了,我们只要制造数据库查询异常就可以模拟该场景。
测试方式:
执行数据库语句alter table executors drop column threads_num; 将mysql中executor表的threads_num字段给删掉。然后重新启动executor。并确保executor可以正常工作。
再次执行覆盖率统计,查看CR平台的结果:
 
 
可以看到,这下“新修改”的代码全部覆盖了。可以妥妥地在jira上标上这功能测试通过。
 
总结
最近看了一些业界的测试方法,发现基于覆盖率统计的白盒测试的热度正在逐渐提升,包括腾讯、去哪儿等一些公司都有基于覆盖率统计指导测试的不少实践。包括分析代码增量覆盖率,分析每条用例对覆盖率的贡献来精简测试用例集、剔除无效用例,基于执行覆盖统计将每条用例与代码模块相对应等等。所幸,我们也有CR平台,基于CR平台,我们后续可以做的事情应该还有很多。https://www.cnblogs.com/znicy/p/9948607.html
50000+
5万行代码练就真实本领
17年
创办于2008年老牌培训机构
1000+
合作企业
98%
就业率

联系我们

电话咨询

0532-85025005

扫码添加微信