持续集成-结合Gitlab API监控Golang单元测试质量

1,697 阅读4分钟

一、捕获Gitlab 事件

 webhook是一种web回调或者http的push API, 可以向其它应用提供实时信息。在Gitlab的 Integrations 里 提供了丰富的gitlab 事件回调方法trigger配置,在远程服务器实现webhook,即可捕获gitlab事件,比如‘Push hook’,‘Issue Hook’,‘Merge Request Hook’,‘Pipeline Hook’,‘Job Hook’等等; 


 每一种回调事件,可以获取对应事件的详细信息,如EventPushHook的数据结构:

 type EventPushHookStruct struct {
    ObjectKind   string `json:"object_kind"`
    Before       string `json:"before"`
    After        string `json:"after"`
    Ref          string `json:"ref"`
    CheckoutSha  string `json:"checkout_sha"`
    UserID       int    `json:"user_id"`
    UserName     string `json:"user_name"`
    UserUsername string `json:"user_username"`
    UserEmail    string `json:"user_email"`
    UserAvatar   string `json:"user_avatar"`
    ProjectID    int    `json:"project_id"`
    Project      struct {
        ...
    } `json:"project"`
    Repository struct {
        ...
    } `json:"repository"`
    Commits []struct {
        ...
    } `json:"commits"`
    TotalCommitsCount int `json:"total_commits_count"`
} 

 因为单元测试属于gitlab的pipeline事件,捕获Gitlab pipeline回调事件,即可提取类型为unittest的job数据,将pipelineid,jobid,name,coverage,commiter,commitevent等数据入库;但是这一步还拿不到详细的单元测试数据,比如测试用例数和成功失败用例数; 流程图示:

 二、配置Gitlab CI

 .gitlab-ci.yml允许用户创建无数多个任务,这些任务可以是并行执行的,也可以是串联执行; 一个任务是由一列参数定义的,来决定任务的工作内容和行为.在变更项目代码后会触发持续集成流程,在.gitlab-ci.yml中配置单元测试任务:

 stages:
- build
- unittest
- deploy
- cleanup

build_job:
  stage: build
  script:
  - make build

test_job:
  stage: unittest
  script:
  - make test 

 stages定义了pipeline执行的先后顺序,通常的顺序是构建、编译、单测、发布,也可以在脚本中做一些清理和初始化工作;


 1、统计用例 

为了获取Golang项目的所有用例数,我们可以在脚本增加这些内容:

- go test -v ./... -list "Test[^(]+" -args -config=../../config/config-test.toml|grep Test

go test ./...会到项目目录下遍历查找所有的测试用例,这里要注意go test有一个特性,在list出所有用例的时候他会预执行用例,如果目录下的第一个用例预执行失败比如panic了,他会放弃这个目录查找下一个目录。也就是说后面的一些成功用例可能会被统计漏掉。所以在执行go test list时不能有panic错误发生。
在列出所有的用例后,我们可以将用例写到文件并发送的远程服务器将用例保存: 

- go test -v ./... -list "Test[^(]+" -args -config=../../config/config-te
st.toml|grep Test > cases && curl -s -X POST -F pipid=$CI_PIPELINE_ID -F jobid=$CI_JOB_ID -F "appname=FastRank-go" -F "file=@./cases" http://testfactory.com/api/ut/uploadcases/api/ut/uploadcases 

是远程服务器的一个http文件处理接口,能将用例根据本次CI_PIPELINE_ID和CI_JOB_ID存储起来; 

 2、执行用例

 保存好本次pipeline的单测用例后,接下来要执行用例并统计用例的成功失败率;

- go test   -v   ./...    -args -config=../../config/config-test.toml|grep -E '^\--- FAIL|^\--- PASS' > result
  &&  cat result- curl -s -X POST   -F  pipid=$CI_PIPELINE_ID   -F  jobid=$CI_JOB_ID  -F "appname=FastRank-go"  -F "file=@./result"   http://testfactory.com/api/ut/updatecases 

 因为使用原生的go test,在统计成功 用例只需过滤“--- PASS”关键字就可以,将结果写到文件,并发送远程服务器;

也许有小伙伴问这里为什么不将curl写到 go test的后面,这里是因为Gitlab CI的job有一个特性,如果job中的某个命令失败了,那么他会认为这个job失败,剩下的命令就不会再执行。所以当go test遇到失败的用例时,为了保证我们能 统计到失败的用例,在 go test 后再 &&一个 无关紧要的命令,保证整个job不会失效; 

同样的,在远程服务器实现api/ut/updatecases文件处理接口,将上一步统计的用例更新状态,并统计个数和成功率; 

 3、统计成功率和覆盖率 

再次执行go test统计项目的覆盖率并生成详细覆盖率报告: 

- go test -v -cover ./... -coverprofile=cover.data -args -config=../../config/config-test.toml
- go tool cover -func=cover.data -o stdout
- go tool cover -html=cover.data  -o report.html 

这一组命令大家应该比较熟悉了,生成覆盖率数据文件,并转成html报告; 

最后将覆盖率报告文件存到远程服务器: 

 - curl -s -X POST -F pipid=$CI_PIPELINE_ID -F jobid=$CI_JOB_ID -F "appname=FastRank-go"
 -F "file=@./report.html" http://testfactory.com/api/ut/uploadfile 

 三、调用Gitlab API 

在管理单元测试持续集成过程中,Gitlab API提供了很多接口可以实时查询任务和项目的相关信息,我们只需使用Gitlab token调用标准接口即可;


 比如获取项目下所有的job、所有的pipeline,retryjob,项目branch等等;

通过前面收集的单元测试用例和job信息,最终可以生成单次pipelinie的单元测试报告;


 四、集成数据

集成用例数据后,测试/开发人员通过Event Server(Testfactory)能清晰查看分析每次单元测试执行情况: 

 1、单测持续集成列表 

 2、覆盖率详细报告 

 3、单测报告