chikaku

且听风吟

永远是深夜有多好。
github
email

Go ランタイムのコードカバレッジの収集

go1.20は、実行時にコードカバレッジを収集する機能を導入しました。

Integration tests のためのカバレッジプロファイリングサポート

以下は、シンプルな HTTP サービスの例です:

func main() {
    var firstVisit atomic.Bool
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        if firstVisit.CompareAndSwap(false, true) {
            w.Write([]byte("Hello first visiter"))
        } else {
            w.Write([]byte("Hello"))
        }
    })

    done := make(chan struct{})
    http.HandleFunc("/exit", func(w http.ResponseWriter, r *http.Request) {
        close(done)
    })

    go func() {
        if err := http.ListenAndServe(":8000", nil); err != nil {
            panic(err)
        }
    }()

    <-done
}

コンパイル時に-coverオプションを追加します。

$ go build -cover

実行時に、カバレッジ情報の出力ディレクトリを指定するためにGOCOVERDIR環境変数を追加し、その後は通常のバイナリを実行するだけです。プロセスが正常に終了した後、指定したGOCOVERDIRディレクトリにカバレッジ関連のファイルが表示されます。プログラムが正常に終了しない場合、パニックや os.Exit によって終了した場合など、出力されるファイルは不完全な場合があります。

# HTTPサーバーを起動
$ GOCOVERDIR=./coverdata ./demo
# インターフェースをテスト
$ http 127.0.0.1:8000/
$ http 127.0.0.1:8000/exit
# 出力ファイルを表示
$ ls coverdata
covcounters.6fd39c6fc688fc732181f8d31bfc2c1f.7892.1677208447525456700
covmeta.6fd39c6fc688fc732181f8d31bfc2c1f

GOCOVERDIRディレクトリには、covcounterscovmetaのファイルが存在します。同じバイナリファイルを複数回実行しても、covmeta ファイルは 1 つしか出力されません。

$ ls coverdata
covcounters.6fd39c6fc688fc732181f8d31bfc2c1f.12377.1677208539436884400
covcounters.6fd39c6fc688fc732181f8d31bfc2c1f.7892.1677208447525456700
covmeta.6fd39c6fc688fc732181f8d31bfc2c1f

次に、go ツールチェーンの新しいcovdatacoverツールを使用して、出力されたカバレッジバイナリファイルを処理します。

$ go tool covdata <mode> -i=<dir1,dir2,...> ...flags...
$ go tool cover {-func,-html} 

サンプル#

カバレッジを直接出力する#

covdataを使用して、コードのテストカバレッジを直接取得し、go test -coverと同じcoverprofileを出力します。

$ go tool covdata percent -i=./coverdata -o profile.txt
    golab/demo      coverage: 83.3% of statements

複数回のテストをマージする#

covdataを使用して、複数回の実行から出力された covcounters ファイルを結合します。-iで複数のディレクトリを指定できます。

$ go tool covdata merge -i=./coverdata -o=merged
$ ls merged
covcounters.6fd39c6fc688fc732181f8d31bfc2c1f.0.1677208798216472900
covmeta.6fd39c6fc688fc732181f8d31bfc2c1f

関数 / 行ごとのカバレッジを表示する#

coverツールを使用すると、具体的な関数やコードのカバレッジ状況を詳細に確認できます。

# 関数ごとに表示
$ go tool cover -func=profile.txt
golab/demo/main.go:8:   main            83.3%
total:                  (statements)    83.3%
# 行ごとに表示し、htmlファイルを出力
$ go tool cover -html=profile.txt
HTML output written to /tmp/cover3154511218/coverage.html

出力された html ファイルを開くと、次のようになります:

coverage.html

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。