多环境多需求并行下的代码测试覆盖率统计工具实现

马蜂窝技术原创内容,更多干货请关注公众号:mfwtech前端

测试覆盖率常被用来衡量测试的充分性和完整性,也是测试有效性的一个度量。「敏捷开发」的大潮之下,如何在快速迭代的同时保证对被测代码的覆盖度和产品质量,是一个很是有挑战性的话题。java

在马蜂窝大交通、酒店等交易相关业务中,项目的开发和测试实践一样遵循敏捷的原则,迭代周期短、速度快。所以,如何依据测试覆盖率数据帮助咱们有效判断项目质量、了解测试状态、提高迭代效率,是咱们一直很重视的工做。数据库

Part.1 测试覆盖率统计中的挑战

对于功能测试而言,一般能够经过充分了解需求、完善的测试用例、接口测试、Review 技术方案等来保证测试充分性。但随着业务规模快速发展,业务逻辑愈来愈复杂,系统级别交互愈来愈多,这些方法都不能保证全部的代码必定被所有测试过,也给测试人员带来极大挑战。后端

说到这儿和你们分享一个由于测试覆盖不充分,影响到线上业务的真实案例。事件原由是项目提测阶段一个微服务 Sonar 扫描没经过,开发同窗为了修复 Sonar 发现的问题而重构了一部分历史代码,却致使一个原有发券需求的错误。当天下午运营触发发券后 Bug 出现直接致使生单不可用,而且持续了将近一个小时。这里的问题就是发券功能与这次需求无关,开发人员修改代码后测试人员不知道,也没有通过测试,但跟随本次需求一块儿上线了,测试用例没法覆盖到。浏览器

经过这个例子能够明显地看到正确统计被测代码覆盖率的重要性。当前市面上统计覆盖率的工具不少,但应用到咱们的实际场景中一般存在如下问题:服务器

  1. 大部分第三方工具都是以支持提测前单元测试的覆盖率统计为主,而支持提测后测试覆盖率的工具则比较缺少架构

  2. 第三方工具提供的覆盖率基本都是展现全量的,但大部分状况下,测试人员重点关注的应该是本次新增和修改的部分,而不是耗费过多精力在未修改的部分上;微服务

  3. 为了支持多需求并行测试,大交通后端服务采用 QA 隔离环境,而市面上尚未支持多需求隔离环境并行测试的测试覆盖率统计工具工具

所以,大交通测试组决定自研工具进行被测代码的覆盖率统计,用代码覆盖结果反向地检查测试人员测试用例的覆盖度和开发人员代码的冗余度,更精准地定位和分析问题,保证产品质量。单元测试

Part.2 覆盖率统计工具设计

结合咱们的实际场景,覆盖率统计工具的实现目标以下:

  1. 大交通业务后端代码使用 Java 语言开发,主要的业务处理逻辑都在后端,因此工具要优先支持 Java 代码覆盖率统计

  2. 能够统计提测后测试过程当中不一样类型测试的覆盖率,包括:手工测试、回归测试、接口测试、UI 自动化测试等等

  3. 支持全量、增量覆盖率统计

  4. 支持多需求多环境并行测试,同时统计覆盖率

  5. 用户不局限于测试人员,而是全部有测试需求的人员,包括开发和测试等

  6. 支持自动化统计,简化操做步骤,无需学习成本,报告简单易懂

咱们将覆盖率统计工具命名为 jCover,并将其引入 CI/CD 体系,与内部 Java 平台项目管理及持续集成系统 MONE 打通。工具设计以下图所示:

图 1:覆盖率工具总体架构图

覆盖率统计的大体流程为首先经过获取多环境服务的配置信息,生成指定环境服务的测试覆盖率文件,而后根据须要生成全量覆盖率报告和增量覆盖率报告,最后,存储测试覆盖率报告到指定环境目录下。

Part.3 主要功能及实现方式

jCover 的主要功能包括:

  • 支持多需求多环境并行测试下,同时统计覆盖率

  • 支持全量覆盖率统计

  • 支持增量覆盖率统计

  • 支持自动/手动统计覆盖率

  • 覆盖率报告统一管理

下面围绕以上功能点,为你们介绍 jCover 的做用、特色和具体实现方式。

1. 覆盖率工具平台化

为了简化操做步骤下降学习成本、报告简单易懂,jCover 支持界面化操做,能够手动生成测试覆盖率报告和查询测试覆盖率报告;查询测试覆盖率报告入口统一,代码测试覆盖率数据清晰,方便数据统计和量化。

图 2:覆盖率报告查询页面

2. 支持多需求多环境下的并行测试

因为使用敏捷迭代,项目多、并行率高,大交通全部微服务均引入测试环境隔离插件,同时支持多项目并行测试。所以,jCover 须要支持多环境并行的测试覆盖率统计。

具体来讲,每一个测试项目都会有一个单独的环境标识,以隔离环境标识+环境类型+服务名称惟一肯定一个覆盖率统计单元;每个覆盖率统计单元都会生成对应的测试覆盖率统计报告,测试覆盖率统计报告被存储到 jCover 部署的服务器中,存储位置是环境标识对应的服务目录下;同一个服务的不一样提测分支同时在多项目中测试时相互间的覆盖率报告不会被覆盖。

多环境并行流程图见下图(目前只支持 QA 环境覆盖率统计):

图 3:多环境并行流程图

例如:隔离环境 gjssqz 和隔离环境 supplyrefund 能够同时进行测试覆盖率统计,隔离环境标识+环境类型+服务名称指定了每一个环境下的单个服务测试覆盖率统计结果。

覆盖率工具 UI 展现以下图:

图 4:用「隔离环境标识+环境类型+服务名称」来标识和统计覆盖率

3. 全量覆盖率统计

在测试时有时候须要关注全量代码的测试覆盖率,代码全量覆盖率统计过程以下:

(1)查询服务信息

jCover 经过内部 Java 平台项目管理及持续集成系统 MONE 来查询被测微服务的信息:

  • 为了减轻对 MONE 系统的压力,设定每日一次定时拉取全量服务信息,将隔离环境标识、服务名称、容器 IP、监听端口、环境类型和状态存储到数据库。

  • 生成覆盖率报告时根据隔离环境标识和服务名称从 MONE 单服务信息拉取接口查询最新的容器 IP。若是数据库没有就新增服务信息,若是数据库有就更新服务对应 IP。

(2)收集覆盖率数据

为了作覆盖率统计,须要从微服务部署的容器中下载测试覆盖率 Dump 文件。咱们采用的解决方案是使用 JavaAgent 代理,首先对微服务部署的容器进行了改造,使得容器支持 JavaAgent 功能;其次为了动态插桩记录被测代码的运行结果,在被测微服务的 JVM 启动脚本中增长 JavaAgent 参数。

覆盖率工具根据 IP 和监听端口经过 JavaAgent 代理从容器中下载 Dump 文件,以环境和服务标识惟一 Dump 文件,并存储到 jCover 所在的服务器。在下载覆盖率数据时采用追加方式,若是该 Dump 覆盖率文件已存在,那么该轮的覆盖率数据会直接在文本末尾进行追加,便于统计整个测试过程的代码覆盖结果。

(3)根据全量覆盖率文件生成全量覆盖率报告

  1. MONE 从微服务容器中拷贝 Class 文件到 jCover 所在服务器指定目录

  2. jCover 经过 Class 文件和 Dump 文件生成全量覆盖率文件

  3. 根据全量覆盖率文件生成全量的测试覆盖率报告,把全量的测试覆盖率报告以「隔离环境标识+服务名称+顺序 ID」的维度存储到 jCover 所在服务器的指定目录

  4. 最后配置静态资源映射规则生成测试覆盖率报告 URL 并把测试覆盖率报告 URL 存储到数据库中

用户打开测试覆盖率工具前端界面就能够在浏览器中查看步骤 D 生成的覆盖率报告了,绿色表示被覆盖,红色表示未被覆盖,黄色表示部分覆盖:

图 5:全量测试覆盖率报告展现

4. 增量覆盖率统计

业务发展到必定阶段后,代码量级很大。主干代码咱们默认是正确的代码。当一个新需求提测后,测试人员更关注的实际上是针对本次需求更改的代码的覆盖率而不是所有代码的覆盖率,想从全量覆盖率报告中找出本次更改的增量代码的覆盖率是很是困难的。基于此问题咱们开发了增量覆盖率统计功能。

增量覆盖率统计和全量覆盖率统计有三个相同的步骤:查询服务信息、收集覆盖率数据、生成全量覆盖率文件。生成全量覆盖率文件后,增量覆盖率统计的不一样点是增长了如下处理:增量代码获取、生成增量覆盖率报告,具体实现以下:

(1)Diff 增量代码

  1. 分别获取每一个微服务的 master 主干和测试分支内容,Diff 测试分支对象和 Master 分支对象,获得增量代码

  2. 滤除增量代码中的非.java 文件

  3. 循环遍历增量代码获得变化行,标识行变化类型包括:新增、更新

(2)生成增量覆盖率报告

  • 根据增量代码变化行标识无变化的方法

  • 在改变的代码行(改变包括增长和更新)行首加上对应的标识:「增长」的代码以「+++」标识,「更新」的代码以「U」标识,同时删除无变化的方法,生成增量代码覆盖率报告

图 6:增量覆盖率流程

下图是交易服务增量覆盖率报告的截图示例,从图中清晰看出增量行和更新行的测试覆盖率状况。

图 7:增量覆盖率报告展现

5. 支持手动/自动统计覆盖率

当测试人员须要查看最新的测试覆盖率时,能够经过「jCover - 生成测试覆盖率报告」的入口手动触发生成测试覆盖率报告。

图 8:手动统计覆盖率图形化界面

在一个需求的实际测试中被测的微服务一般有多个。由于修改 Bug 等缘由,被测微服务常常须要重启,重启后容器销毁,JavaAgent 插桩后的文件也会被删除致使重启前覆盖的代码没法被统计。

若是每次重启每一个被测微服务前都须要测试人员手动生成覆盖率报告的话,是个很大的工做量也会常常被遗忘。所以 jCover 经过和发布系统结合实现了覆盖率自动统计功能。具体实现方法为 jCover 提供了自动生成覆盖率文件接口,在服务重启部署时后端发布系统调用此接口,实现自动统计覆盖率,无论服务重启多少次均可以把每次测试时覆盖的代码所有统计到。

以前大交通的后端服务发布系统为 Jenkins,后续升级为了 MONE,两种发布系统下均支持服务部署时自动统计覆盖率。

Part.4 工具效果

通过一段时间推广使用和优化,如今大交通全部的需求提测后均使用 jCover,主要体现出如下几点优点:

  • 能够支撑不一样类型的覆盖率测试。jCover 能够统计手工测试、接口测试、回归测试、UI 自动化测试等各类类型测试的所有覆盖率,展现为一份覆盖率报告。

  • 及时发现漏测代码。经过使用测试覆盖率工具能够发现测试用例未覆盖的代码,反推测试用例缺失。例如在「虚舱管理」项目中国际交易支付前校验失败发送 MQ 消息没有覆盖,测试人员补充了支付前校验失败发消息的测试用例;在「国际搜索坑位供应商及价格优先级设置」项目中发现因为 Mock 数据的局限性, 带有辅营的加价代码未覆盖,补充了机票+辅营的测试用例,提升测试覆盖度。

  • 发现开发的冗余代码。例如:在「国际机票重复预订优化项目」中发现冗余代码,getBaseOrderDetail 方法无调用方,开发进行了删除。

  • 及时发现测试中的问题并改进,提升测试效率。在「国内供应商资源统一化」项目中测试人员执行了不少测试用例后,使用 jCover 查看覆盖率报告发现应该覆盖的代码未被覆盖,与开发沟通后发现控制这部分代码逻辑的开关是「关闭」状态,此开关应该是在「打开」状态进行测试

  • 为上线代码审批提供数据参考。当团队成员申请代码上线时,开发 TL 能够重点关注未覆盖部分代码,减小线上问题发生。

  • 辅助提高测试人员对被测代码的熟悉度。

Part.5 近期规划

目前 jCover 只支持查看每个类覆盖行和未覆盖行是什么,可是对于一个微服务总体行覆盖率是多少没有统计,咱们正在开发增量覆盖率百分比,帮助开发和测试作出准确的判断。目前也在调研前端的覆盖率统计,下一步将实现前端的覆盖率统计工具 jCover。

在平常需求测试中能够采用测试(手工测试、接口测试、回归测试等)+jCover 覆盖分析的测试方法来完善测试场景,减小测试遗漏,确保测试的充分性,但须要注意的是 jCover 统计只能展现哪些代码被覆盖了,代码的正确性仍是须要用例的执行结果正确来保障;还有时候开发会漏开发某部分需求,此时依靠 jCover 是没法发现这部分遗漏代码的,所以除了 jCover 以外能够经过参与技术评审、编写用例时参考产品功能矩阵图等多种手段发现问题,全方位保障被测代码的质量。

以上就是对马蜂窝大交通测试覆盖率统计工具 jCover 的分享。固然,统计代码覆盖率仅仅是一种手段,覆盖率高不必定表明质量好,但覆盖率不高的代码质量风险确定很高。只有清楚在覆盖率统计数据背后反映出的问题,才能从根本上保证软件总体的质量。

本文做者:代春美,马蜂窝测试部-交易测试工程师;孙海燕,马蜂窝测试部-交易测试团队负责人。

相关文章
相关标签/搜索