代码覆盖率统计平台,为京东主App黄金流程研发团队,在日常迭代开发过程中,孵化出来的一个可以辅助回归测试、量化测试数据、提高测试质量的创新平台。包括轻量级代码覆盖率收集SDK、覆盖率分析系统、覆盖率提升辅助系统、覆盖率可视化管理平台、自动化报告,数据统计分析等部分。下边我们将分别从代码覆盖率平台的底层实现及当前发展概况这两个方面进行一个简单的介绍。
在百度百科中,对代码覆盖率的描述是这样的:
代码覆盖(英语:Code coverage)是软件测试中的一种度量,描述程序中源代码被测试的比例和程度,所得比例称为代码覆盖率。
简单而言,就是度量代码执行情况的一个指标。在日常的工作和开发中,代码覆盖率通常被用来衡量单元测试用例执行情况;或者是衡量测试人员在回归测试过程中,测试任务的完成情况。总结一下,执行代码覆盖率扫描有以下意义:
1. 代码覆盖率反映单元测试用例对代码的覆盖程度,一份好的单元测试用例,执行后,相对应的覆盖率会更高。因此,覆盖率正面反映了测试用例的好坏。
2. 单元测试用例编写过程中,可以结合未覆盖的语句、条件判断等,对单元测试用例进行补全。因此,覆盖率执行情况可以反过来指导测试用例编写。
3. 测试同学在回归测试过程中,代码执行情况、Mock数据覆盖情况、测试任务进度情况,均无法数字化衡量,此时,代码覆盖率的引入,将这一过程数字化。
4. 依赖代码覆盖率执行结果,测试同学可以反推前期测试数据设计,发掘测试用例设计盲点,有助于完善测试用例;研发同学可以优化代码,提高代码质量
5. 代码覆盖率,尤其是增量覆盖率,在日常迭代开发中,每个版本之间增量代码的执行情况,直接关系到本次上线需求的测试覆盖情况,影响上线需求质量。
综上所述,代码覆盖率统计,在提高单元测试质量、完善测试用例、优化代码、保障需求质量及测试过程数字化这几个方面,具有非常重要的意义。
代码覆盖率扫描,在日常的开发中,的确具有很重要的意义,那么,开发中我们应该如何实现覆盖率扫描呢,或者如何获得覆盖率扫描报告呢,下边我们将区分Android和iOS端,进行分别说明。
Android这边我们使用Jacoco进行覆盖率扫描核心工具。Jacoco是一个开源的Java代码覆盖率扫描工具,支持JVM,支持多个第三方工具的集成,例如 Sonar、Jenkins等,使用上非常灵活,导出报告中,可以将代码执行过程中的行覆盖、类覆盖、方法覆盖、分支覆盖、指令覆盖、圈复杂度等信息展示给用户,且在Java代码的覆盖率扫描中,有着得天独厚的优势,因此在技术选型方面几乎是单选题,下边简单介绍一下Jacoco的两种模式:
Jacoco使用插桩的方式来记录覆盖率数据,是通过一个probe探针来注入,主要有两种插桩模式:
1. on-the-fly模式
JVM通过 -javaagent参数指定jar文件启动代理程序,代理程序在ClassLoader装载一个class前判断是否修改class文件,并将探针插入class文件,探针不改变原有方法的行为,只是记录是否已经执行。
2. offline模式
在编译阶段,完成了对java文件的插桩,生成了插过桩的class文件或者jar包,测试同学在使用接入jacoco的测试包进行回归测试中,触发了探针,完成收集后,生成覆盖率信息到文件,最后统一进行对比处理,生成报告。
目前在我们的客户端工程中,主要使用offline模式,在打包集成阶段,就已经完成了文件的插桩,将编译过程中生成的插桩文件,上传至服务端,并按照指定规则进行存档,方便用户在测试App过程中将执行记录以文件形式上传后,进行对比分析,生成覆盖率测试报告。
调研目前市场上iOS覆盖率检测方案,主要有两种,如下:
上述方案的痛点:
1. 仅支持在本地运行连线调试,生成覆盖率报告,无法推广其他业务部门,以及测试同学使用。
2. 不支持生成增量覆盖率报告。开发、测试同学更多关注此次发版的新增和修改部分。
3. 不支持覆盖率的多版本合并,会导致重复测试工作量。
基于京东组件化的实现方案,结合现有的业务开发流程,我们设计了一套代码覆盖率生成方案。
2.2.1 获取插桩文件
首先需要在Xcode中配置编译选项:
GCCGENERATETESTCOVERAGEFILES = YES
GCCINSTRUMENTPROGRAMFLOWARCS = YES
编译后会为每个可执行文件生成对应的 .gcno 文件,代码中调用覆盖率分发函数会生成对应的 .gcda 文件
我们使用自研的JDWorkSpace Mac客户端,支持获取组件的插桩文件,同时生成已插桩的静态库。
2.2.2 JDWorkSpace
为了其他业务部门更方面的接入,我们自研了JDWorkSpace平台。
该平台提供以下服务:
1. 动态插入版本号、覆盖率配置选项
2. 编译组件、发布release版本 framework
3. 文件监控、数据实时同步
4. 数据压缩、上传插桩文件、framework至VPM服务器。
2.2.3 获取操作文件
为了更方便的获取用户操作文件,我们开发了JDCodeCoverRateModule组件,支持如下功能:
1. 支持可视化UI界面,悬浮展示;
2. 支持任意拖拽自动吸附屏幕边缘功能;
3. 工具页面提供覆盖率统计数据写入、数据压缩、数据上传、数据清理四个功能。
2.2.4 生成覆盖率报告
LCOV作为GCC Code Coverage的开源前端工具,支持行、函数、分支覆盖的报告输出。因此我们使用LCOV作为iOS代码覆盖率生成工具。
2.2.5 增量覆盖率报告
基本思路如下:
1. 采集全量覆盖率
2. 采集代码diff
3. 根据代码diff和全量覆盖率过滤出增量覆盖率
前边我们介绍了代码覆盖率统计在日常开发过程中给我们带来的优势,以及我们在Android和IOS端的一些技术选型工作。下边将继续介绍我们在京东主站App上,是如何进行代码覆盖率统计,及如何完成智能覆盖率提升,也就是我们的质量保障平台(VPM系统)。
依下图所述,覆盖率扫描平台整体包含覆盖率接入收集SDK、覆盖率统计分析引擎、覆盖率辅助提升系统、覆盖率可视化管理平台、自动化报告推送系统等5部分。
本着一键接入、对代码尽可能侵入较小的目标,将覆盖率执行结果收集、生成、上报、清理、重置等功能进行了SDK封装,对接入部分需要的依赖、任务创建、策略配置等部分功能,封装了Gradle插件封装,各个模块插件在接入时,只需要简单的配置即可使用。
该引擎主要负责以下功能:接入管理、任务解析、工作空间创建、代码分支管理、解析生成报告、页面数据存储、消息推送等。
配置中心部分:开放给指定管理员用户,管理员用户登录后,除了用户权限配置外,还可以进行接入模块配置。管理员在后台配置界面,分别输入模块名称,模块ID,以及需配置模块的代码仓库地址信息,提交后,VPM系统后台首先会创建工作空间。工作空间内部主要进行模块之前的隔离,包含源码管理、执行脚本管理、测试操作执行文件管理、全量覆盖率、增量覆盖率报告管理等工作。工作空间创建以后,分别进行脚本初始化,代码Clone,Android工程会在代码clone完成以后,进行预编译,生成代码覆盖率插桩文件,方便后续进行比对生成覆盖率报告。
任务调度部分: 任务调度部分,以任务为主线,客户端SDK上传的覆盖率执行文件,以任务ID+时间戳命名,VPM服务端接收到该文件后,先进行云端存储,然后读取任务ID,匹配工作空间,匹配用户配置信息(客户端类型、当前分支、需要对比的目标分支信息等),初始化脚本(覆盖率报告的生成,依赖脚本语言),在生成脚本后,会根据客户端是Android还是IOS进行区分处理。Android先进行Gradle编译,然后,依赖编译生成文件进行全量及增量覆盖率生成。而IOS这边在打包阶段已经完成了插桩文件的生成及上传,因此可以直接按照build号,匹配对应的插桩文件,生成报告。后边的文件存储及前台数据刷新,不再赘述。
数据服务部分:数据服务,主要对每一个任务ID关联的模块信息、版本信息、代码分支信息、及覆盖率信息进行存储及展示,针对管理员用户,还提供了页面访问PV,停留时长、接入模块统计以及测试人员纬度的测试进度等数据展示。整个数据服务部分,将代码测试情况、模块接入情况及测试人员测试进度情况数字化的呈现给团队,并可以通过邮件推送、咚咚消息推送等渠道,周知给团队内每一个人。
通过上述SDK接入,测试人员在客户端同步任务ID后,可以开始进行正常的回归测试或者是功能测试。SDK会依据预先配置的策略进行插桩执行信息统计,写入文件中,完成上传。服务端任务执行完毕后,可以在VPM平台,进行增量、全量报告的查看。
Android增量报告展示:
iOS增量报告展示:
介绍完覆盖率全量、增量报告后,我们下一步想要提?覆盖率数据应该如何操作呢,这?我们提供了覆盖率辅助提升系统,下边将进行介绍。
覆盖率辅助提升系统,目的是为了帮助测试同学提高每一个任务的覆盖率数据,从而完善测试用例,保障测试质量。在覆盖率扫描系统推广使用过程中,我们也和多位测试同学进行了深入沟通,其中有一项就是测试人员如何提升覆盖率,了解到测试同学在提升覆盖率过程中,主要面临以下几个问题:
1. 代码逻辑不清楚:虽然从报告中可以很容易的获取到代码的执行情况,但是对于未执行的代码,不清楚需要什么样的业务逻辑才能触发。
2. 测试数据找不到:测试同学有提到,虽然可以通过阅读代码及相应的注释,知道部分逻辑,但是如何触发这部分逻辑,需要什么样子的测试数据触发未执行的逻辑,依然不清楚。
3. 增量覆盖率提升较全量覆盖率提升更难:增量覆盖率目标代码仅仅是每一个迭代需求变更导致的一些代码修改,而全量报告测试则需要全部代码的覆盖率,如何构造各种类型订单数据,也是测试同学面临的一个问题
鉴于上述问题,我们搭建了“覆盖率辅助提升系统”,其主要作用为,线上数据抓取、缓存、筛选、Mock、执行,提高覆盖率。
整个流程总结下来,比较简单,在接入过程中,对需要监控的接口服务接入JMQ服务,然后在后台配置页面对监控的接口、关键字段进行配置,配置完成后,生成数据抓取及存储策略,等待JMQ消息通知。
核心能力分为三部分,分别为数据存储、筛选及对接Mock平台。存储和筛选这部分逻辑,为基本的数据存储和读取逻辑。我们不再赘述。在VPM平台筛选到合适数据后,可以一键插入Mock平台,客户端同步插入数据后,使用Mock数据进行代码逻辑触发及覆盖率提高。同时VPM筛选到的数据,可以在编辑后进行保存,方便开发、测试同学依据代码逻辑,进行数据调整。
上述主要简单的介绍了我们在覆盖率报告全量报告和增量报告生成过程中,做的一些研究及目前的成果,虽然核心功能大多依赖第三方能力,但是我们在开发、调试及推广过程中,也产生了许多的技术积累,方便后续对进行源码重写及优化。
覆盖率扫描平台,目前在京东主站黄金流程已经开始了接入和使用,订单、收银台、结算、购物车等模块,均完成了一期功能接入和使用。支持增量、全量报告按照任务纬度生成和查看,支持智能提升平台数据抓取和Mock,支持用户使用情况统计、分模块整体覆盖率统计等。后续我们在二期规划中,将继续优化覆盖率报告、优化覆盖率扫描平台用户体验,优化智能化提升平台,让覆盖率提升更加智能化。