chikaku

且听风吟

永远是深夜有多好。
github
email

Go 実行時コードカバレッジ収集

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

統合テストのためのカバレッジプロファイリングサポート

以下は簡単な HTTP サービスの例です:

func main() {
    var firstVisit atomic.Bool
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        if firstVisit.CompareAndSwap(false, true) {
            w.Write([]byte("こんにちは、最初の訪問者"))
        } else {
            w.Write([]byte("こんにちは"))
        }
    })

    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 ディレクトリ内にカバレッジ関連のファイルが表示されます。プログラムが異常終了した場合、例えば panic や 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 ファイルが存在し、同じバイナリファイルを複数回実行しても、1 つの covmeta ファイルのみが出力されます

$ 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 出力が /tmp/cover3154511218/coverage.html に書き込まれました

出力された HTML ファイルを開くと以下のようになります:

coverage.html

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