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

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

Avatar for hiro hiro
February 27, 2023

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

Avatar for hiro

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