- tl;dr;
- Goで複数パッケージ構成の場合何が問題か?
- GitHubの場合
- GitLabの場合
- 本題:GitLabで複数パッケージ構成のGoプロジェクトのカバレッジを集計したい
- .gitlab-ci.ymlのサンプル
tl;dr;
gcov + lcovが無難
Goで複数パッケージ構成の場合何が問題か?
Goでテストを実行する時に -cover
をつけるとお手軽にカバレッジが集計できるのですが、1パッケージずつしか出力されないので複数パッケージ構成のプロジェクトの時にプロジェクト全体のカバレッジが集計できずに困ります。*1
$ go test -count=1 -cover ./... ok gitlab.com/sue445/tanuki_reminder 0.066s coverage: 77.2% of statements ok gitlab.com/sue445/tanuki_reminder/enum 0.026s coverage: 100.0% of statements
GitHubの場合
にもあるように
-coverprofile coverage.out
でgcov形式で出力- jandelgado/gcov2lcov-action でlcov形式に変換
- GitHub Actions使ってない場合は https://github.com/jandelgado/gcov2lcov を直接使う
- lcovファイルをCoverallsに送信
が今の所最適解だと思います。
GitLabの場合
GitHubと違いGitLabはカバレッジ集計に標準対応しているというのがあります。
https://docs.gitlab.com/ee/ci/pipelines/settings.html#test-coverage-parsing
CIのログに出力されたテストカバレッジっぽい文字列を正規表現で抽出するという割と力技な仕組なのですが、各言語のデファクトツールに関してはだいたい正規表現が用意されています。
GitLabのリポジトリ上で正規表現を設定しておくだけで最終的にリポジトリ上でカバレッジの推移のグラフが見れます。 *2
Coverallsに比べればだいぶ貧弱なのですがリポジトリに標準機能でついているという強みはあります。
もしこれで困る場合はCoverallsのような他ツールを使うか*3、lcovで生成したカバレッジレポートをGitLab Pagesにアップロードすればいいと思います。
本題:GitLabで複数パッケージ構成のGoプロジェクトのカバレッジを集計したい
tanuki_reminder だと当初 /coverage: \d+.\d+% of statements/
のような正規表現でカバレッジを収集してたのですが、1つのログに複数のカバレッジが出ていると後の方にあるものがそのジョブのカバレッジとして採用されて複数パッケージ構成になった時に変なことになりました。*4
いくつか手法を考えたのですが、lcovのgenhtmlコマンドでHTML形式のカバレッジレポートを作る時にプロジェクト全体のカバレッジがログに出力されることに着目してこいつを利用するようにしました
.gitlab-ci.ymlのサンプル
test: image: golang:1.15 stage: test variables: GCOV2LCOV_VERSION: v1.0.4 script: - mkdir -p coverage/ - go test -coverprofile coverage/coverage.out -covermode atomic ./... # Install and run gcov2lcov - wget https://github.com/jandelgado/gcov2lcov/releases/download/${GCOV2LCOV_VERSION}/gcov2lcov-linux-amd64.tar.gz -q -O - | tar xvzf - --strip 1 - chmod 755 gcov2lcov-linux-amd64 - export GOROOT=$(go env GOROOT) - ./gcov2lcov-linux-amd64 -infile "coverage/coverage.out" -outfile "coverage/coverage.lcov" # Install and run lcov - apt-get update - apt-get install -y lcov - genhtml coverage/coverage.lcov -o coverage/ # regular expression for genhtml coverage: '/lines.*\d+\.\d+%/' artifacts: paths: - coverage/
- 実際に使ってる設定ファイル : https://gitlab.com/sue445/tanuki_reminder/-/blob/ab2ba5120000c6038209603604dbd632b0ee6309/.gitlab-ci.yml#L49-77
- カバレッジ集計を修正した時のMR : https://gitlab.com/sue445/tanuki_reminder/-/merge_requests/60
lcovを使ってるので後半部分はGo以外でも流用できそう
*1:Go 1.15時点では
*2:https://gitlab.com/sue445/tanuki_reminder/-/graphs/master/charts
*3: https://docs.coveralls.io/gitlab を見る感じGitLab CI対応はしてそうに見える
*4:https://gitlab.com/sue445/tanuki_reminder/-/jobs/836453936