玩过Go覆盖率的同学当有所了解,Go的覆盖率方案最初的设计目标仅是针对单测场景,导致其局限性很大。而为了适配更多的场景,行业内各种博客、插件、黑科技介绍也层出不穷。当然,过去我们也开源过Go系统测试覆盖率收集利器 - goc,算其中比较完善,比较系统的了。且从用户使用角度来看,goc也确实解决了行业内很多同学的痛点。

而现在,Go官方终于开始正式这个问题了。作者Than McIntosh 于今年3月份提出了新的覆盖率提案,且看当前实现进度,最快Go1.20我们就能体验到这个能力,非常赞。

基于作者的Proposal,我们先来看看这个提案细节。

新姿势: go build -cover

需要明确的是,本次提案不会改变原来的使用姿势go test -cover,而是新增go build -cover使用入口。从这一变化我们不难看出,新提案主要瞄准的是 "针对程序级的覆盖率收集" ,而旧版的实际是 "仅针对包级别的覆盖率收集" ,二者设计目标有明显的差别。

在新姿势下,使用流程大体是:

$ go build -o myapp.exe -cover ...
$ mkdir /tmp/mycovdata
$ export GOCOVERDIR=/tmp/mycovdata
$ <run test suite, resulting in multiple invocations of myapp.exe>
$ go tool covdata [command]

整体逻辑也比较清晰:

  1. 先编译出一个经过插桩的被测程序
  2. 配置好覆盖率输出的路径,然后执行被测程序。到这一步程序本身就会自动的输出覆盖率结果到上述路径了
  3. 通过 go tool covdata 来处理覆盖率结果

这里的子命令 covdata 是新引入的工具。而之所需要新工具,主要还是在新提案下,输出的覆盖率文件格式与原来的已有较大的差别。

新版覆盖率格式

先来看旧版的覆盖率结果:

  mode: set
cov-example/p/p.go:5.26,8.12 2 1
cov-example/p/p.go:11.2,11.27 1 1
cov-example/p/p.go:8.12,10.3 1 1
cov-example/p/p.go:14.27,20.2 5 1

大家当比较熟悉,其是文本格式,简单易懂。

每一行的基本语义为 "文件:起始行.起始列,结束行.结束列 该基本块中的语句数量 该基本块被执行到的次数"

但缺点也明显,就是 "浪费空间". 比如文件路径 cov-example/p/p.go, 相比后面的counter数据,重复了多次,且在通常的profile文件,这块占比很大。

新提案在这个方向上做了不少文章,实现细节上稍显复杂,但方向较为清晰。

通过分析旧版的每一行能看出,本质上每一行会记录两类信息,一是定位每个基本块的具体物理位置,二是记录这个基本块的语句数量和被执行的次数。虽然执行的次数会变化,但是其他的信息是不变的,所以全局上其实只要记录一份这样的信息就好,而这就能大大的优化空间,

所以,新版覆盖率它实际会实际输出两份文件,一份就是meta-data信息,用于定位这个被测程序所有包、方法等元信息,另一份才是counters,类似下面:

➜  tmp git:(master) ✗ ls -l
total 1280
-rw-r--r-- 1 jicarl staff 14144 Nov 28 17:02 covcounters.4d1584597702552623f460d5e2fdff27.8120.1669626144328186000
-rw-r--r-- 1 jicarl staff 635326 Nov 28 17:02 covmeta.4d1584597702552623f460d5e2fdff27

这两份文件都是二进制格式,并不能直观的读取。但是借助covdata工具,可以轻松转化为旧版格式,比较优雅。类似:

go tool covdata textfmt -i=tmp -o=covdata.txt

ps: tmp 是覆盖率文件所在目录。

真 • 全量覆盖率

一个标准的go程序,基本上由三种类型的代码包组成:

  • 自身代码
  • 第三方包,通过mod或者vendor机制引用
  • go标准库

在过去,几乎所有的工具都只关注业务自身代码的插桩,鲜少关注第三方包,更别说go官方标准库了。这在大部分场景下是没问题的,但有时有些场景也有例外,比如SDK相关的项目。因为这时候SDK会作为Dependency引入,要想对其插桩就需要额外的开发量。还比如一些CLI程序,执行完命令之后,立马就结束了,也是非常不利于覆盖率收集的。

这些问题都是很现实的,且我们在goc项目中也收到过真实的用户反馈:

不过,现在好了,新版覆盖率方案也有实际考虑到这些需求,它实际会做到 支持全量插桩+程序退出时主动输出覆盖率结果 的原生方式,非常值得期待。

更多覆盖率使用场景支持: 合并(merge)、删减(subtract)、交集(intersect)

在实际处理覆盖率结果时,有很多实用的场景,在新提案中也有提及,比如支持:

  • 合并多次覆盖率结果 go tool covdata merge -i=<directories> -o=<dir>
  • 删减已经覆盖的部分 go tool covdata subtract -i=dir1,dir2 -o=<dir>
  • 得到两份结果的交集 go tool covdata intersect -i=dir1,dir2 -o=<dir>

在过去,这些场景都需要依赖第三方工具才行,而在新方案中已经无限接近开箱即用了。

不过更复杂的场景,类似远程获得覆盖率结果等(类似goc支持的场景),看起来新方案并没有原生支持。这个问题,笔者也在issue 讨论中提出,看看作者是否后续有解答。

展望与不足

值得注意的是新提案的实现是通过 源码插桩+编译器支持 的方式来混合实现的,与原来go test -cover 纯源码改写的方式有了较大的变化。

另外作者提到的 test "origin" queries 功能还是非常让我兴奋的,因为有了它,若想建立 测试用例到源码的映射 会变得简单很多,甚至更进一步的 精准测试,也变的更有想象空间。不过这个功能不会在Go1.20里出现,只能期待以后了。

作者还提到了一些其他的限制和将来可能的改进,比如 Intra-line coverage, Function-level coverage, Taking into account panic paths 等,感兴趣的同学可以自行去Proposal文档查看。

Go1.20 新版覆盖率方案解读的更多相关文章

  1. SpringBoot 2.0 + Apache Dubbo 2.7.3 最新版整合方案

    前言 2018年2月16日,Apache Dubbo 加入 Apache 基金会孵化器.2019年5月16日,Apache 软件基金会董事会决议通过了 Apache Dubbo 的毕业申请,这意味着 ...

  2. 20. ClustrixDB explain参数解读

    ClustrixDB有一个流模型,它从容器(表和索引)开始并通过操作符图对行进行流处理.ClustrixDB有一组丰富的操作符,随着更多功能和优化的添加,这些操作符偶尔会增加.我们使用一个地方来记录操 ...

  3. 20、手把手教你Extjs5(二十)模块Grid的多列表方案

    对于有很多字段的模块在一个grid中显示所有的字段,会显得很臃肿,对于不同的用户其侧重的字段类型也不尽相同,因此就有必要为Grid的列表设计多个方案.在这个自定义系统进行设计的时候,我已经将这部分内容 ...

  4. 1-STM32物联网开发WIFI(ESP8266)+GPRS(Air202)系统方案升级篇(方案总揽)

    我的这个升级篇的代码适用于自己所有的带WIFI和GPRS模块的开发板,升级功能实质上是通过MQTT把数据发给WIFI和GPRS模块,然后模块进行保存和运行. 这个升级程序是当时自己花了两个星期的时间写 ...

  5. 百度大脑UNIT3.0详解之语音语义一体化方案

    在电话客服场景里,用户和机器人交流的过程中,经常会出现沉默.打断机器人.噪声等情况,机器人在应对这些异常情况的时候,需要语音和语义理解技术进行处理,才能实现用户和机器人的流畅交谈.而这些能力的获取与应 ...

  6. Go 开发关键技术指南 | 敢问路在何方?(内含超全知识大图)

    作者 | 杨成立(忘篱) 阿里巴巴高级技术专家 Go 开发关键技术指南文章目录: 为什么你要选择 Go? Go 面向失败编程 带着服务器编程金刚经走进 2020 年 敢问路在何方? Go 开发指南大图 ...

  7. 移动性能测试 | 持续集成中的 Android 稳定性测试

    前言 谈到Android稳定测试,大多数会联想到使用monkey工具来做测试.google官方提供了monkey工具,可以很快速点击被应用,之前我有一篇帖子提到了monkey工具的使用,详见: htt ...

  8. 程序员Y先生投保案例分享

    大家好,我是闲鱼君.我在2018年底搞了个副业,做了保险经纪人.保险经纪人是为用户服务的第三方机构,找经纪人买保险省钱.省力.保险一次就买对,而且还能提供后续理赔服务,具体可以看我的文章<201 ...

  9. Redis入门及环境搭建

    一:Redis简介 Redis(Remote Dictionary Server 远程字典服务)是一个开源的(BSD许可的)内存数据结构存储,用作数据库.高速缓存和消息队列代理. Redis提供五大基 ...

  10. STP详解-STP、RSTP、MSTP

    STP详解 01 冗余链路中存在的问题 如图所示LSW1和LSW2之间有两条线路相连,它们之间任何一条链路出现故障另外一条线路可以马上顶替出现故障的那条链路,这样可以很好的解决单链路故障引起的网络中断 ...

随机推荐

  1. Openstack neutron:云数据中心底层网络架构

    目录 - 目录 - 云数据中心流量类型 - NSX整体网络结构 - 管理网络(API网络) - 租户网络 - 外联网络 - 存储网络 - openstack整体网络结构 - 管理网络:(上图中蓝线) ...

  2. 我的 Kafka 旅程 - Linux下的安装 & 基础命令

    准备工作 安装解压缩工具 tar # 检查是否安装了解压缩工具 tar yum list tar # 如未安装 tar yum install tar -y 安装必备的 java # 检查是否安装了 ...

  3. 10.第九篇 kube-scheduler 安装及验证

    文章转载自在:https://mp.weixin.qq.com/s?__biz=MzI1MDgwNzQ1MQ==&mid=2247483830&idx=1&sn=787de8d ...

  4. 组件化开发1-git命令简洁版

    1-给项目添加git git init 2-查询当前状态,(红色显示的为在工作区,绿色为暂缓区) git status 3-提交到暂缓区 git add . 4-提交到本地仓库('xxxx'里面为注释 ...

  5. slf4j、log4j2及logback使用

    slf4j.log4j2及logback使用 1.问题来源 之前看过关于slf4j.log4j2及logback的介绍,slf4j是门面,log4j2及logback是具体实现,仅使用slf4j门面是 ...

  6. Upscayl,免费开源的 AI 图像增强软件

    有的时候我们找遍了全网却难以找到一张模糊图片的原图,这时候我们想如果能够一键将图片变成高清的就好了.其实这正是计算机视觉的一大研究反向--图形增强,通过AI计算将模糊的图片增强,将几百kb的低像素图片 ...

  7. 糟了,线上服务出现OOM了

    前言 前一段时间,公司同事的一个线上服务OOM的问题,我觉得挺有意思的,在这里跟大家一起分享一下. 我当时其实也参与了一部分问题的定位. 1 案发现场 他们有个mq消费者服务,在某一天下午,出现OOM ...

  8. SpringCloud微服务实战——搭建企业级开发框架(四十七):【移动开发】整合uni-app搭建移动端快速开发框架-添加Axios并实现登录功能

      uni-app自带uni.request用于网络请求,因为我们需要自定义拦截器等功能,也是为了和我们后台管理保持统一,这里我们使用比较流行且功能更强大的axios来实现网络请求.   Axios ...

  9. Mybatis笔记02-----MyBatis的核心配置文件以及模糊查询的实现

    认识MyBatis核心配置文件mybatis-config.xml 这个文件名是随意可以起,但为了规范一般都命名为mybatis-config.xml:配置文件与MyBatis的行为和属性信息息息相关 ...

  10. 解决pip下载速度慢问题

    解决pip下载速度慢的问题 痛点:当我们pip 安装第三方库的时候,由于是访问的国外地址,所以会出现下载很慢!干等..... 解决方案: # 1.在C盘目录-->Users-->用户--& ...