Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Go1.20 リリースパーティ 統合テストのカバレッジ計測

hiro
February 27, 2023

Go1.20 リリースパーティ 統合テストのカバレッジ計測

hiro

February 27, 2023
Tweet

More Decks by hiro

Other Decks in Programming

Transcript

  1. カバレッジレポートファイル • レポートファイルは2種類 ◦ カバレッジ情報を含む covcounters.xxxx ◦ ソースコードのメタ情報を含む covmeta.xxxx •

    どちらもバイナリ形式である。go test -coverprofileコマンドで出力されるレポートとは異なる形 式(go tool coverでは解析できない) $ ls _coverage covcounters.b8766fa017dad81194d2a53bce9517fa.50700.1676182425749415000 covmeta.b8766fa017dad81194d2a53bce9517fa
  2. カバレッジレポート解析用の新しいツール • レポート解析にはgo tool covdataコマンドを使う • 関数単位、パッケージ単位でのカバレッジ集計が可能 • go tool

    coverで解析できるテキスト形式への変換もサポートされている $ go tool covdata percent -i=_coverage main coverage: 83.3% of statements $ go tool covdata textfmt -i=_coverage -o coverage.txt
  3. 複数レポートの解析 • go tool covdataでは複数のテスト実行結果を組み合わせた集計が可能 ◦ merge (test1 + test2) ◦

    subtract  (test1 - test2) ◦ intersection (test1 & test2) • E2Eテストのカバレッジと、 API自動テストのカバレッジをそれぞれとって組み合わせるなど $ go tool covdata merge -i=_coverage,_coverage2 -o merged
  4. 制約を回避する方法 • runtime/coverageパッケージ(https://pkg.go.dev/runtime/coverage)を使う • 実行途中でカバレッジレポートを出力可能 ◦ func ClearCounters() error ◦

    func WriteCounters(w io.Writer) error ◦ func WriteCountersDir(dir string) error ◦ func WriteMeta(w io.Writer) error ◦ func WriteMetaDir(dir string) error • io.Writerを引数にとれるので好きな場所に出力できる ◦ 例えばクラウドストレージへのアップロードなど
  5. まとめ • go build -coverでカバレッジ計測用のバイナリを生成できる • バイナリを実行するとカバレッジレポートが出力される ◦ レポートの解析には go

    tool covdataを用いる ◦ プログラムが正常終了しないとレポートが出力されないという制約がある • runtime/coverageで実行途中にカバレッジレポートを出力できる       => 統合テストのカバレッジを計測できるようになった
  6. カウント用のデータ構造が大きく変更 var goCover_a7a39b72f297_P uint32 var goCover_a7a39b72f297__0 [5]uint32 var goCover_a7a39b72f297_M =

    [...]byte{ 0x7a, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x1, ... } // _P = pkgId // __0[0] = <num_units> // __0[1] = pkgId // __0[2] = fnId // __0[3:] = count of a unit // _M = meta-data var GoCover_0_613761333962373266323937 = struct { Count [2]uint32 Pos [3 * 2]uint32 NumStmt [2]uint16 } { Pos: [3 * 2]uint32{ 5, 6, 0xa000d, // [0] 6, 8, 0x3000a, // [1] }, NumStmt: [2]uint16{ 1, // 0 1, // 1 }, } before Go1.20
  7. 計測用のコード生成の変化 • before ◦ ファイル1つずつに実行カウント用の変数( GoCover)を生成 ▪ GoCoverはコードブロックの位置情報と実行回数を保持 ▪ ファイル名とGoCoverを_testmain.goで紐づける(coverRegisterFile)

    • 1.20 ◦ 1パッケージの複数ファイルをまとめて goCoverを生成 ▪ goCoverはパッケージID、関数ID、ユニット(ブロック) No.、実行回数を保持 ▪ 位置情報やファイル名はメタデータに集約 (https://github.com/golang/go/blob/master/src/internal/coverage/defs.go) ▪ goCover変数に関する情報を coveragecfgファイルに出力してコンパイラに渡す
  8. go test -coverの内部で叩かれているコマンド golang/1.20/go/pkg/tool/darwin_arm64/cover -pkgcfg ./pkgcfg.txt -mode set -var goCover_a7a39b72f297_

    -outfilelist ./coveroutfiles.txt /sample/main.go /sample/sub.go golang/1.19.5/go/pkg/tool/darwin_arm64/cover -mode set -var GoCover_0_613761333962373266323937 -o ./main.cover.go /simple/main.go golang/1.19.5/go/pkg/tool/darwin_arm64/cover -mode set -var GoCover_1_613761333962373266323937 -o ./sub.cover.go /sample/sub.go before Go1.20 tool coverに pkgcfgを渡して、複数ファイルまとめて処理している
  9. 今後の展望 • カバレッジ計測用のデータ構造が変更されたことでより柔軟な集計・解析が可能になる予定 • proposalの一例 ◦ if conditionA || conditionB

    {} で、条件ごとに別個でカウント ◦ 行単位でなく関数単位でのカバレッジ計測 ◦ ある行を実行するテスト関数のリストアップ ◦ https://go.googlesource.com/proposal/+/master/design/51430-revamp-code-coverage.md
  10. 参考情報 • レポート出力されるメタデータの定義 ◦ https://github.com/golang/go/blob/master/src/internal/coverage/defs.go • Go 1.20 リリース連載 go

    build に追加される cover オプション(利用例付き) ◦ https://future-architect.github.io/articles/20230203a/ • proposalの一例 ◦ https://go.googlesource.com/proposal/+/master/design/51430-revamp-code-coverage.md