GoのカバレッジをCoberturaを使ってJenkinsで表示する
JenkinsでGoのカバレッジをグラフィカルに出したいなと思い調べてみたら
gocover-coberturaというライブラリを使うと実現できるということだったのでまとめてみました。
前提
- Go 1.10.3
- Jenkins 2.121.3
- Go plugin 1.2
- Cobertura Plugin 1.12.1
- dep 0.5.0
概要
CoberturaはJava用のカバレッジツールなのでGoで使うためには変換が必要になります。
パイプラインスクリプトの大まかな流れとしては下記です。
まずmakeのスクリプト内部でカバープロファイルを取得します。
取得したカバープロファイルをgocover-coberturaでCobertura用のXML変換にします。
最後に変換したXMLをCobertura Pluginでグラフィルカルに表示します。
make
go testでカバレッジを取得しようとした時にパラメータを指定しないと
テストが実行されたファイルだけが対象となってしまいます。
この状態でカバレッジを集計するとカバーしているパッケージは必ず100%になってしまうため本来欲しいものが取得できません。
-coverpkgというパラメータを指定するとその対象のディレクトリが全てカバレッジの計算対象になります。
なので今回は-coverpkgを使って本当に欲しいカバレッジを取得するようにしています。
テスト時のコマンドは下記のようになります。
go test -coverprofile=${カバープロファイル} -coverpkg=${対象ディレクトリ} ${対象ディレクトリ}
実際に実行されるコマンドは下記のようになります。
go test -coverprofile=bin/cover.out -coverpkg=./example/... ./example/...
binディレクトリの下はGitの管理対象外ディレクトリとしていることを想定しています。
こういうのはどこに置けばいいのかわからなかったのですが他に適切な場所があればそちらに置くのが良いです。
gocover-coberturaでXMLに変換
gocover-coberturaを使ってカバープロファイルをXMLに変換します。
パイプラインスクリプトでは毎回gocover-coberturaを取得するようにしています。
stage("Prepare") {
steps {
sh 'go get -u github.com/t-yuki/gocover-cobertura'
}
}
makeコマンドで取得したカバープロファイルを読み込ませます。
sh "gocover-cobertura < bin/cover.out > bin/cover.xml"
ここはgocover-cobertura公式のサンプルコマンドとほぼ同じです。
Coberturaプラグイン
最後にCobertura Pluginを使ってグラフィルカルに表示します。
cobertura (
autoUpdateHealth: false,
autoUpdateStability: false,
coberturaReportFile: 'bin/cover.xml',
conditionalCoverageTargets: '70, 0, 0',
failUnhealthy: false,
failUnstable: false,
lineCoverageTargets: '80, 0, 0',
maxNumberOfBuilds: 0,
methodCoverageTargets: '80, 0, 0',
onlyStable: false,
zoomCoverageChart: false
)
coberturaReportFileに先ほど変換したXMLファイルのパスを指定するだけです。
生成されたXMLの内容
CoberturaはJava用のツールであるため変換されたXMLもJavaに則した内容になっています。
Javaはクラスベースなのでカバレッジの取得もクラスがある前提で集計されます。
Goの場合はクラスがないのでどういう集計をしているのだろうかと思って結果を見てみたところ
1構造体=1クラス、レシーバのない関数は-というクラスに属するものとして集計しているようです。
これはgocover-coberturaの仕様のようです。
まとめ
といことでJenkinsでカバレッジを取得できるようになりました。
-coverpkgの情報をなかなか見つけられずに苦労しましたが
最終的に出来上がったスクリプトでは難しいことは特にしていないと思います。
わかってしまえばお手軽にできるので簡単にカバレッジ取得できますね。