本文来自网易云社区css
做者:倪志风java
最近一直对测试覆盖率方面的内容比较感兴趣,虽然不少项目都早已经用上了Jacoco来实现测试覆盖率的统计,可是不多看到实际项目中基于覆盖率统计来指导测试的实践。这篇文章是我近期基于代码变动风险(CR)平台 (http://cr.qa.netease.com/)对猛犸大数据系统的后台调度组件Azakban的一个小版本的测试实践。
mysql
我的认为,代码覆盖率应该是对一个版本测试状况的一个重要考量。不能说代码覆盖率高,就是没有风险。可是,相反,我以为若是代码覆盖率很低,那就是客观地存在较大风险,说明咱们测试的充分度不够。CR平台,实际上是基于jacoco覆盖率统计的结果之上,将提测版本与基准版本(一般是上一个线上稳定版本)的代码库进行比对,统计出一个版本提测后开发变动代码的覆盖状况。另外,借助了其余开源工具(ckjm、javancss等)展现了代码中类之间的相互调用关系以及复杂度信息等等。git
下面是我在猛犸4.8.5版本中,借助CR平台对Azkaban相关需求的测试实践:sql
例子一: 数据库
1. 看需求和JIRA 服务器
开发写的需求: 并发
“ 补数据优化,加强顺序性,优化实例生成数量:原来有的逻辑是Trigger每一个一分钟触发一次,而后产生一个补数据实例到分发队列,分发队列每次分发前,先检查有没有正在运行的实例,若是没有就随机选择一个实例分发下去执行。若是有,从新放回队列。这个逻辑存在的问题是,会产生大量的实例在分发队列,耗费内存和CPU时间。如今作的优化是:Trigger每次触发前,先检查分发队列以及已经分发下去的实例里边是否有相关的补数据实例。若是有,则跳过此次触发。另外能够经过 az.backfill.concurrent.num 指定补数据实例产生的并发度(范围1~100,缺失默认值 1)。”工具
看着可能有点晕,我稍微将它简化一下就是: gitlab
a. 补数据调度,本来可能会产生大量并发执行的实例,如今限制并发实例数只能是1。即:前一次实例执行完成后,后一次调度实例才会生成。
b. 提供参数, az.backfill.concurrent.num来控制容许的并发实例数量,该参数的范围是1-100。
至于JIRA,我这边就不重复添图了,大体跟需求内容差很少。
2. 查看Gitlab:
开发提交gitlab代码时与jira作了关联,点击连接能够直接跳转到gitlab:
能够看到该jira影响的类有两个,分别是:GlobleAttribute.java (只添加了一行常量定义)和 TriggerManager.java
3. 查看CR:
开始测试该功能前,先看一眼CR的覆盖状况(CR以前执行过自动化测试用例和其余手工测试用例):
能够看到,在表格里没有出现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平台,咱们后续能够作的事情应该还有不少。
网易云免费体验馆,0成本体验20+款云产品!
更多网易研发、产品、运营经验分享请访问网易云社区。
相关文章:
【推荐】 责任链模式的使用-NettyChannelPipeline和MinaIoFilterChain分析
【推荐】 用户研究如何获取更为真实的用户信息