首先,向项目推广者@CarlJi 和项目的所有 contributors 致敬。

背景

之前 go 代码的覆盖率收集一直是参考有赞的做法,缺点是不能很好的放到集群使用,只能在本地进行覆盖率,虽然也刚好契合了公司的测试模式,但始终效率有限也不够友好,后来发现了goc这个项目,简单方便,而且可以很好的在集群使用,只是收集覆盖率还是需要去 pod 执行,因此考虑把相关操作用 shell 脚本编写,然后打成镜像放到同一集群环境进行覆盖率采集

实现思路

说干就干,我们先使用simple-go-server在本地做实验,把待测服务和 goc server 启动好

先看一下 goc 获取覆盖率的相关命令

goc profile --center=url:port > coverage.out 

这里需要指定 goc server 的地址和需要获取覆盖率的服务注册端口,也就是 127.0.0.1:49748,把它们抽取为变量

#!/bin/bash
export URL
export PROT

set -e

URL=${URL:-'http://127.0.0.1'}
PROT=${PROT:-'49748'}

goc profile --center=${URL}:${PROT} > coverage.out 

这样一个基本脚本就好了,但是执行一次肯定是不够的,继续优化一下,增加一下频率控制和执行开关

while true
do 
    if [ ${SWITCH} -eq 0 ];then
        GET_COVER
    else
        echo 'cover suspend'
    fi
    sleep ${FREQUENCY}
done

现在执行脚本,可以获取到 out 文件了,但是可以看到 out 文件不够直观,当然可以把 out 转为 html,但是我想要的是一个能持续更新具体覆盖情况的效果

为了这个效果,考虑自己写一个简单的服务端(flask)和前端页面,获取到覆盖率后把 html 作为参数发送过来存好,然后前端定时请求接口

然后我在快写完的时候发现我可以直接用 sonar 啊!!!为什么要自己写

脚本继续加入 sonar 的执行命令

sonar-scanner \
    -Dsonar.projectKey=${NAME} \
    -Dsonar.sources=. \
    -Dsonar.go.coverage.reportPaths=coverage.out \
    -Dsonar.projectVersion=${NUM} \
    -Dsonar.host.url=${SONARURL} \
    -Dsonar.login=${TOKEN} \
> /dev/null

执行一下,发现 sonar 没获取到正确到结果

检查后发现是因为当前目录下没有相关代码,需要增加 cd 到正确目录的逻辑,没有代码的话直接 clone 一份到当前目录然后进去

if ! echo `pwd` | grep ${CODEDOCUMENT} > /dev/null;then
        if [ ! -d ${CODEDOCUMENT} ];then
            git clone ${CODEURL}
        fi
        cd `pwd`/${CODEDOCUMENT}
    fi

好,基本逻辑弄好了,那接下来就是把脚本打成镜像,放到集群,然后在 pod 里配置好环境变量就可以在线上测试的时候边测边获取到测试覆盖率了

感谢

这个工具真的很方便,因为对 go 不了解,还有很多功能和细节不了解,只是按照自己的需求简单的使用了一下,真的是很强大好用的工具

再次感谢能把它开源


↙↙↙阅读原文可查看相关链接,并与作者交流