全栈代码测试覆盖率及用例发现系统的建设和实践(上)

发表于:2022-7-12 09:50

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:DP FE    来源:掘金

  1. 背景
  随着项目不断深入迭代,业务逻辑以及用户场景日渐复杂,补充和维护单元测试维护的成本也变得越来越高。测试覆盖质量通过测试用例评审或者人工 Code Review 的方式费时费力,单凭多方沟通和经验累积的方法,往往不够准确,也难以避免开发人员存在在代码上线前“夹带私货”的场景,并且没有量化的、直观的客观数据来支撑。
  为了在有限的时间及人力成本内保证项目质量,实现对项目质量的精细化管理,我们研发了 Finder —— 全栈代码测试覆盖率及用例发现系统(下文简称 Finder),通过精确化的数据量化代码质量,从而实现精准化测试。本文将介绍 Finder 的总体架构,以及它作为质量保障体系中的重要一环,如何在项目中实现精确化测试。
  2. Finder 项目介绍
  Finder 主要分为两个模块,一个是测试过程中对代码测试覆盖率进行收集与统计,一个是分析代码和用例的映射关系,精准确定回归测试范围。
  代码测试覆盖率统计模块,能够满足多环境、多需求、多服务的复杂测试场景,实时收集测试过程中的覆盖率信息,并生成覆盖率统计报告;其支持多端语言接入(Web、React Native、Golang),实现前后端项目全覆盖,打通整体研发流程。
  相关用例发现模块,针对变动的代码分析函数调用关系,追溯完整的调用关系链路,标记出所影响的 API 接口及相关用例,确定测试回归范围。
  3. 架构设计
  Finder 分为代理层、应用层、核心服务层三个模块:
  代理层 Finder Agent,负责前期数据采集的工作,包括编译阶段的代码插桩、覆盖率数据的采集、解析源码函数调用关系信息等;
  应用层 Finder Platform,包含需求信息管理、分支信息管理、单文件覆盖率染色图展示、API 信息展示、测试用例关联、函数调用链展示等页面模块;
  核心服务层 Finder Server,其中,覆盖率分析和服务调用分析是最主要的两个模块:
  覆盖率分析,对收集到的覆盖率数据进行数据聚合、差异增量分析、数据修正等操作;
  服务调用分析,将源码解析工具传输来的数据进行数据结构转换后,完成调用拓扑图生成、API 信息关联、测试用例发现等操作。
  在前期完成数据采集的接入工作后,测试人员无需额外操作,正常进行业务测试,测试完成后可以在可视化平台中查看覆盖率数据、相关测试用例等信息。
  4. 实现方案
  4.1 代码测试覆盖率模块
  代码覆盖率模块主要分为两个步骤,第一步是通过对项目源码插桩,采集覆盖率信息;第二步是对覆盖率信息进行分析,通过可视化平台展示统计报告。
  步骤一:插桩与数据采集
  代码插桩,意为在程序中插入一些代码,用于跟踪被测程序的某些信息。对于覆盖率测试而言,插桩的目的是检测程序中可执行语句被执行(即被覆盖)的情况。
  Finder 支持 JS 和 Golang 两种程序语言的代码覆盖率统计,接入成本低,对业务需求无侵入性。
  对于 JS 程序,我们在 babel 编译阶段进行插桩操作,注入到全局对象 window 中。我们提供了上报覆盖率数据的 npm 包 —— coverage-report,前端应用接入后会主动上报数据到 Finder Server;
  Golang 程序的覆盖率接入对业务项目零侵入,只需要引入 Finder Agent —— 覆盖率收集工具:它在编译阶段对源码插桩,包括 Git 信息和覆盖率信息注入;插桩完成后的服务会启动一个统计覆盖率的 Http Server,Finder Server 通过该 Http Server 提供的接口定时请求覆盖率数据。
  步骤二:差异覆盖率统计
  比起全量代码的覆盖率,实际上我们更关心改动代码部分的覆盖率情况。可以通过 Git 指令对比功能分支与 master 分支的代码差异,过滤无关代码,只针对改动代码部分进行覆盖率统计。
  为实现差异覆盖率的计算,我们约定以行(line)作为维度的结构表示 Git 代码差异和覆盖率信息,满足两者一一对应的关系。
  首先将 Git 分支对比得到的 Diff 数据转换成以代码行作为索引的数组格式,元素的值有空值和 + 两种枚举值:
  空值代表没有改动;
  + 代表有改动。
  覆盖率数组也转换成以代码行作为索引的数组格式,元素的值有 -1、0、1 三种枚举值:
  -1 代表无需统计覆盖率的代码(例如空格,注释等);
  0 代表未覆盖的代码(尚未执行);
  1 代表已覆盖的代码(已被执行)。
  将 Diff 数据与覆盖率数组进行合并,将非改动代码的覆盖率值置为 -1。得到最终的差异覆盖率数据。
  关键问题一:数据源标准化
  由于不同程序语言上报的覆盖率数据结构都不一致,我们需要将数据源标准化,统一转化以行(line)为维度的数组结构。
  首先,前端应用上报的覆盖率数据包含三种维度的覆盖率数据:
  Statement Coverage:语句维度的覆盖率数据;
  Branch Coverage:条件维度的覆盖率数据,例如 if/else、switch、三元运算符等;
  Function Coverage:函数维度的覆盖率数据。
  对于这三类覆盖率,我们做出以下数据转换:
  我们采用与操作将三类覆盖率数据合并为行覆盖率,即一行代码满足三类覆盖率才算被执行过。
  而后端 Golang 服务采集的覆盖率数据,如下图。
  同样,我们也需要将其转换为行维度的数组结构。
  本文内容不用于商业目的,如涉及知识产权问题,请权利人联系51Testing小编(021-64471599-8017),我们将立即处理
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号