Go服务自动触发单元测试覆盖率

一、用到的工具

  • Gitlab
  • Jenkins
  • Shell
  • go test

二、实现原理

在gitlab上配置jenkins的webhook,当有代码变更时自动触发jenkins构建job,job内的shell脚本负责把覆盖率报告以钉钉群通知的方法发送出去。

三、Jenkins job配置

点击上图中的“高级”,出现下图后,点击“Generate”,生成Secret token。

四、Gitlab配置webhook

五、Shell脚本

touch last_num.txt

fi

#存储本次.go文件和_test.go文件的个数,作为上次数据
echo $this_time_go_num > ./this_time_go_num.txt
echo $this_time_test_go_num > ./this_time_test_go_num.txt
echo $this_time_per > ./this_time_per.txt

#获取上次的.go文件数,如果没有则创建文件
if test -e last_time_go_num.txt
then
last_time_go_num=$(cat last_time_go_num.txt)
echo $last_time_go_num
else
touch last_time_go_num.txt
fi

#获取上次的test.go文件数,如果没有则创建文件
if test -e last_time_test_go_num.txt
then
last_time_test_go_num=$(cat last_time_test_go_num.txt)
echo $last_time_test_go_num
else
touch last_time_test_go_num.txt
fi

#获取上次的per,如果没有则创建文件
if test -e last_time_per.txt
then
last_time_per=$(cat last_time_per.txt)
echo $last_time_per
else
touch last_time_per.txt
fi

#计算两次.go文件数的差
go_num_diff=`expr $this_time_go_num - $last_time_go_num`
echo $go_num_diff

#计算两次test.go文件数的差
test_go_num_diff=`expr $this_time_test_go_num - $last_time_test_go_num`
echo $test_go_num_diff

#计算两次占比的差
this_time_test_go_num_init=$(printf "%d" $(($this_time_test_go_num*100/$this_time_go_num)))
last_time_test_go_num_init=$(printf "%d" $(($last_time_test_go_num*100/$last_time_go_num)))
per_diff=$(printf "%d%% " $(($this_time_test_go_num_init-$last_time_test_go_num_init)))
echo $per_diff

cd -
echo "生成Html报告"
go tool cover -html=cover.out -o coverage.html
cp coverage.html /Users/xes/CI/reports/xxx-unitcover/a_this_time_html_report/this_time_coverage.html

# 构造知音楼通知text的内容
cd $this_path
this_time=$(cat this_num.txt)
last_time=$(cat last_num.txt)
now=$(echo $this_time|cut -b 1,2,3,4)
last=$(echo $last_time|cut -b 1,2,3,4)
change=$(echo | awk "{print $now - $last}")

# 设置secret
secret=""
# 设置Webhook
xxx_robot_path=

access_token=

# URL Encode 函数

function urlencode() {
local LANG=C
local length="${#1}"
i=0
while :
do
[ $length -gt $i ]&&{
local c="${1:$i:1}"
case $c in
[a-zA-Z0-9.~_-]) printf "$c" ;;
*) printf '%%%02X' "'$c" ;;
esac
}||break
let i++
done
}

# 执行函数
function run() {
# 获取时间戳
cur_sec_and_ns=`date '+%s-%N'`
cur_sec=${cur_sec_and_ns%-*}
cur_ns=${cur_sec_and_ns##*-}
cur_timestamp=$((cur_sec*1000+cur_ns/1000000))
echo "当前时间戳:"$cur_timestamp
# 获得签名
sign=`echo -n -e "$cur_timestamp $secret" | openssl dgst -sha256 -hmac $secret -binary | base64`
echo "加密后签名:"$sign
# 对签名进行 urlencode
sign_urlencode=`urlencode $sign`
echo "urlencode 后签名:"$sign_urlencode
url_action=""
url_encode=`urlencode $url_action`
echo $url_encode
request_url=$yach_robot_path"&timestamp="$cur_timestamp"&sign="$sign_urlencode
echo "最终请求的 URL:"$request_url

curl -X POST
$request_url
-H 'content-type: application/json'
-d '{
"msgtype": "action_card",
"action_card": {
"title": "单测统计xxx",
"markdown": "### *_test.go占比(不含vendor) | 统计----------- | 本次------ | 上次------ | 新增 | | :--- | :--- | :--- | :--- | | .go | '"$this_time_go_num"' | '"$last_time_go_num"' | '"$go_num_diff"' | | test.go | '"$this_time_test_go_num"' | '"$last_time_test_go_num"' | '"$test_go_num_diff"' | | test.go/.go | '"$this_time_per"' | '"$last_time_per"' | '"$per_diff"' | ### *_test.go覆盖率(平均值) | 本次------ | 上次------ | 差值 | | :--- | :--- | :--- | | '"$this_time"' | '"$last_time"'| '"$change"' | #### 本次&上次覆盖率HTML报告(点击打开) '"$url_action"'",
"image": "https://sentry.io/_assets/screenshots/features-page-dash-12c65431808e7d8daf234a096446c1f0da311a0f3bcec5352e28bda60136fb16.jpg",
"content_title": "xxx单测覆盖率统计",
"single_title": "点击此处,在侧边栏查看HTML报告",
"single_url": ""
}
}'
}

run

#把本次的覆盖率赋值给上次
cp this_num.txt last_num.txt

#把本次的.go文件值给上次
cp this_time_go_num.txt last_time_go_num.txt

#把本次的test.go文件值给上次
cp this_time_test_go_num.txt last_time_test_go_num.txt

#把本次的per值给上次
cp this_time_per.txt last_time_per.txt

#用本次的HTML报告覆盖上次的HTML报告
cd ..
cp a_this_time_html_report/this_time_coverage.html b_last_time_html_report/last_time_coverage.html

避坑:

在slave机器上git clone遇到一个小坑,如下图:

原因是slave机器上的git默认账号对此gitlab仓库权限不足,解决方法是给git clone命令加上username和password

六、Go test 命令

如步骤五中所示,用到2个go test命令,如下:

go test ./... -coverprofile=cover.out                               # 生成.out文件

go tool cover -html=cover.out -o coverage.html        # 生成Html报告

七、钉钉群通知

钉钉机器人配置:

钉钉机器人的安全设置方式有3种,我们这里选择方式一“自定义关键词”

添加钉钉机器人:

请求字段说明:

注意:请求的content中(content即link的值,也就是在text或title中包含)必须包含钉钉机器人的“自定义关键词”,比如我们curl请求中就包含了“单元测试”,否则会报如下图的错误

八、通知消息展示

钉钉群接收到的通知消息:

原文地址:https://www.cnblogs.com/ailiailan/p/13222036.html