Go1.20でサポート予定の統合テスト用カバレッジプロファイリングを触る
本記事はGo Advent Calendar 2022 14日目の記事になります
Go1.20のリリースで統合テストのためのカバレッジプロファイリングがサポートされる予定です
以前まではユニットテストレベルのものでしかカバレッジを計測することができませんでしたが、go test
以外のプログラムの実行や統合テストでもカバレッジの計測ができるようになるみたいです
リリースノート
概要
-
go build
に新しいオプション-cover
をつけることでカバレッジ計測可能なバイナリをビルドできる - バイナリ実行時に
GOCOVERDIR=
でプロファイルの出力フォルダを指定することでカバレッジを計測できる -
GOCOVERDIR
のデータを操作するためのツールcovdata
がGo1.20で追加される - カバレッジ計測の仕組みを全体的に刷新する構想があり、それに準拠したアップデートになっている
使ってみる
gotip のインストール
リリース前の機能を使うのでgotipをインストールします
去年のAdvent Calenderでgotipについての記事を書きました
この記事で紹介しているインストール手順が使えます$ go install golang.org/dl/gotip@latest
$ gotip download
$ gotip version
go version devel go1.20-b16e94d13d Mon Dec 12 23:10:52 2022 +0000 linux/amd64
テスト対象の準備
至極シンプルなコードを用意
package main
func main() {
if false {
// Should not be executed.
fmt.Println("OgoOgo")
}
fmt.Println("GoGo")
}
module example.com/main
go 1.20
統合テストの実施
ビルド
いつものビルドコマンドに-cover
オプションを追加することで、カバレッジ計測が可能なバイナリをビルドできます
$ gotip build -cover .
$ ls
go.mod main main.go
実行
ビルドしたバイナリを利用して統合テスト(今回は手で実行するだけ)を実行します
実行時にGOCOVERDIR=
でプロファイルの出力フォルダを指定してやることで計測結果が出力されます
GOCOVERDIR
を指定せずに実行すると警告warning: GOCOVERDIR not set, no coverage data emitted
が表示され、プロファイルは出力されません
$ mkdir coverdir
$ GOCOVERDIR=coverdir ./main
GoGo
指定したcoverdirディレクトリにプロファイルが出力されました
$ ls coverdir/
covcounters.5524194b4db04f800f58090476d5dc3b.741.1670935339179650175
covmeta.5524194b4db04f800f58090476d5dc3b
カバレッジはカウンターデータファイル(covcounters.xxx)とメタデータファイル(covmeta.xxx)に分かれて保存されます
メタデータファイルにはソースファイル名や関数名など実行ごとに不変な項目が保存され、カウンターデータファイルはプログラムの実行記録が保存されます
したがって、バイナリを複数回実行するとカウンターデータファイルが複数作成されます
依存パッケージがある場合、ビルド時に-coverpkg
オプションも併せて利用すると依存パッケージのプロファイルのも計測できます(メインモジュールのものもここにないものは除外されます)
解析
Go1.20からGOCOVERDIR
のデータを操作するためのツールcovdata
が導入される予定です
percent
サブコマンドを使うことでカバレッジデータを解析できます
$ gotip tool covdata percent -i=coverdir
example.com/main coverage: 66.7% of statements
textfmtセレクタを使うことでgo test -coverprofile=
と同じ形式の出力も可能なので、
go tool cover -html
でhtmlに変換もできます
$ gotip tool covdata textfmt -i=coverdir -o profile.txt
$ gotip tool cover -html=profile.txt -o profile.html
よく見る形式のhtmlが出力できました
このcovdataは他にも色々サブコマンドが実装されています
usage: go tool covdata [command]
Commands are:
textfmt convert coverage data to textual format
percent output total percentage of statements covered
pkglist output list of package import paths
func output coverage profile information for each function
merge merge data files together
subtract subtract one set of data files from another set
intersect generate intersection of two sets of data files
debugdump dump data in human-readable format for debugging purposes
詳細については、新たに用意された統合テスト用カバレッジプロファイリングのガイドページをご覧ください
アップデートの背景
ツールを使っていて go tool cover
や go test -cover
といった既存の仕組みに則ることをせず、go build -cover
や go tool covdata
という新しい仕組みを作って統合テストのカバレッジ計測を実現していることに疑問を覚えたのですが、Proposalを見るとその意図がかいてありました
この提案は以下の課題解決を目的にしており、これは既存の仕組みでは解決しきれないもののため、カバレッジシステムを全体的に刷新しようと動いているそうです
- アプリケーション全体でのカバレッジを計測するのが困難。複数のバイナリを利用するアプリケーションや、複数回バイナリを実行するテストシナリオに対応できない
- 今のカバレッジレポートの形式はフラットで、大規模なアプリケーションのテストを想定したものになっていない
- cmd/coverやgoコマンドで使用されるソースからソースへの書き換えに起因する問題がある
今後ユニットテストも含めて統合的にカバレッジ計測ができるようすることも考えているみたいで、アップデートがとても楽しみです
まとめ(冒頭の概要と同じ内容)
-
go build
に新しいオプション-cover
をつけることでカバレッジ計測可能なバイナリをビルドできる - バイナリ実行時に
GOCOVERDIR=
でプロファイルの出力フォルダを指定することでカバレッジを計測できる -
GOCOVERDIR
のデータを操作するためのツールcovdata
がGo1.20で追加される - カバレッジ計測の仕組みを全体的に刷新する構想があり、それに準拠したアップデートになっている
Discussion