golang-parallel-test-by-github-actions-and-merge-coverage-report
by
SatoKeiju
Link
Embed
Share
Beginning
This slide
Copy link URL
Copy link URL
Copy iframe embed code
Copy iframe embed code
Copy javascript embed code
Copy javascript embed code
Share
Tweet
Share
Tweet
Slide 1
Slide 1 text
GitHub ActionsでGoの テストを並列実行し カバレッジレポートを作る 2024/12/11 @DMM.go プラットフォーム開発本部 第一開発部 ポイントクラブグループ webチーム デザインエンジニア @SANdglAss
Slide 2
Slide 2 text
● 2021年に新卒で入社したバックエンドエンジニア ● 3年目からは「デザインエンジニア」としてUI/UXデザインや UXライティングも担当中 くわしくは「デザインエンジニア」で検索 🔍 自己紹介
Slide 3
Slide 3 text
GoプロジェクトのCIをCircleCI → GitHub Actionsに
Slide 4
Slide 4 text
● とある事情で移行することに ● 無事すべて移行できた ● テストジョブの所要時間が1分半 → 5分になった GoプロジェクトのCIをCircleCI → GitHub Actionsに
Slide 5
Slide 5 text
GoプロジェクトのCIをCircleCI → GitHub Actionsに なんでやねん ● とある事情で移行することに ● 無事すべて移行できた ● テストジョブの所要時間が 1分半 → 5分になった
Slide 6
Slide 6 text
遅くなった主な理由: マシンスペック(コア数) Docker 実行環境の使用 - CircleCI GitHub Actions CircleCI About GitHub-hosted runners - GitHub Enterprise Cloud Docs ↑のドキュメントはエンプラですが Cloudも同じです
Slide 7
Slide 7 text
CIに詳しいマリーアントワネット
Slide 8
Slide 8 text
CIに詳しいマリーアントワネット 「スペックが足りないなら 強いのを使えばいいじゃない」
Slide 9
Slide 9 text
CIに詳しいマリーアントワネット 「スペックが足りないなら 強いのを使えばいいじゃない」 → 現状のDMM Organizationでは使えない ...
Slide 10
Slide 10 text
CIに詳しいマリーアントワネット
Slide 11
Slide 11 text
CIに詳しいマリーアントワネット 「コアが少ないならノード並列で 分割実行すればいいじゃない」
Slide 12
Slide 12 text
CIに詳しいマリーアントワネット 「コアが少ないならノード並列で 分割実行すればいいじゃない」 → それでいきましょう
Slide 13
Slide 13 text
1つのジョブを並列実行: CircleCI編
Slide 14
Slide 14 text
1つのジョブを並列実行: CircleCI編 とてもかんたん
Slide 15
Slide 15 text
1つのジョブを並列実行: GitHub Actions編
Slide 16
Slide 16 text
1つのジョブを並列実行: GitHub Actions編 ない
Slide 17
Slide 17 text
1つのジョブを並列実行: GitHub Actions編 なんでやねん ない
Slide 18
Slide 18 text
1つのジョブを並列実行: GitHub Actions編 ジョブを並列実行する仕組み自体は、ないわけではない
Slide 19
Slide 19 text
1つのジョブを並列実行: GitHub Actions編 ジョブを並列実行する仕組み自体は、ないわけではない その名も matrix ワークフローでのジョブのバリエーションの実行 - GitHub Docs
Slide 20
Slide 20 text
1つのジョブを並列実行: GitHub Actions編 ジョブを並列実行する仕組み自体は、ないわけではない その名も matrix 変数のパターンを 列挙しておくと ワークフローでのジョブのバリエーションの実行 - GitHub Docs
Slide 21
Slide 21 text
1つのジョブを並列実行: GitHub Actions編 ジョブを並列実行する仕組み自体は、ないわけではない その名も matrix 各値が設定された ジョブが並列で 立ち上がる ワークフローでのジョブのバリエーションの実行 - GitHub Docs 変数のパターンを 列挙しておくと
Slide 22
Slide 22 text
1つのジョブを並列実行: GitHub Actions編 ジョブを並列実行する仕組み自体は、ないわけではない その名も matrix 各値が設定された ジョブが並列で 立ち上がる 変数のパターンを 列挙しておくと どうにかして 使えないものか ... ワークフローでのジョブのバリエーションの実行 - GitHub Docs
Slide 23
Slide 23 text
Rubyで用いし先駆者がいた
Slide 24
Slide 24 text
Rubyで用いし先駆者がいた GitHub Actions でテストを並列化して CI 時間を短縮する - Gunosy Tech Blog
Slide 25
Slide 25 text
Rubyで用いし先駆者がいた GitHub Actions でテストを並列化して CI 時間を短縮する - Gunosy Tech Blog 並列化したい数だけ IDを宣言しておいて
Slide 26
Slide 26 text
Rubyで用いし先駆者がいた GitHub Actions でテストを並列化して CI 時間を短縮する - Gunosy Tech Blog 並列化したい数だけ IDを宣言しておいて 全テストをいい感じに 各IDに割り振って
Slide 27
Slide 27 text
Rubyで用いし先駆者がいた GitHub Actions でテストを並列化して CI 時間を短縮する - Gunosy Tech Blog 並列化したい数だけ IDを宣言しておいて 各ノードは自分の IDの テストだけ実行 全テストをいい感じに 各IDに割り振って
Slide 28
Slide 28 text
Rubyで用いし先駆者がいた GitHub Actions でテストを並列化して CI 時間を短縮する - Gunosy Tech Blog 並列化したい数だけ IDを宣言しておいて 各ノードは自分の IDの テストだけ実行 全テストをいい感じに 各IDに割り振って これをGoでも やりたい!
Slide 29
Slide 29 text
Goでのテスト分割は(とりあえず)パッケージ毎で
Slide 30
Slide 30 text
Goでのテスト分割は(とりあえず)パッケージ毎で これが
Slide 31
Slide 31 text
Goでのテスト分割は(とりあえず)パッケージ毎で これが こうなりました
Slide 32
Slide 32 text
Goでのテスト分割は(とりあえず)パッケージ毎で これが こうなりました パッケージのパスを列挙して
Slide 33
Slide 33 text
Goでのテスト分割は(とりあえず)パッケージ毎で これが こうなりました パッケージのパスを列挙して テスト対象外の パッケージを 除外して (無くてもいいしいくつあってもいい )
Slide 34
Slide 34 text
Goでのテスト分割は(とりあえず)パッケージ毎で これが こうなりました パッケージのパスを列挙して 行番号を4(並列数)で割ったあまり == 自分のid なら担当 テスト対象外の パッケージを 除外して (無くてもいいしいくつあってもいい )
Slide 35
Slide 35 text
Goでのテスト分割は(とりあえず)パッケージ毎で これが こうなりました パッケージのパスを列挙して テスト対象外の パッケージを 除外して (無くてもいいしいくつあってもいい ) 行番号を4(並列数)で割ったあまり == 自分のid なら担当 よし!いけるぞ! と言いたいところだが ...
Slide 36
Slide 36 text
唯一の懸念点: カバレッジレポートどうしよう
Slide 37
Slide 37 text
Goは素晴らしい言語なので $ go test -cover ./... -coverprofile=<ファイル名>.out でテスト時にカバレッジのプロファイルを吐き出しておき $ go tool cover -html=<ファイル名>.out -o <ファイル名>.html でカバレッジレポートを作れる 唯一の懸念点: カバレッジレポートどうしよう
Slide 38
Slide 38 text
唯一の懸念点: カバレッジレポートどうしよう Goは素晴らしい言語なので $ go test -cover ./... -coverprofile=<ファイル名>.out でテスト時にカバレッジのプロファイルを吐き出しておき $ go tool cover -html=<ファイル名>.out -o <ファイル名>.html でカバレッジレポートを作れる でもnノードで分割実行したら細切れのカバレッジレポートが n個できちゃう
Slide 39
Slide 39 text
唯一の懸念点: カバレッジレポートどうしよう Goは素晴らしい言語なので $ go test -cover ./... -coverprofile=<ファイル名>.out でテスト時にカバレッジのプロファイルを吐き出しておき $ go tool cover -html=<ファイル名>.out -o <ファイル名>.html でカバレッジレポートを作れる でもnノードで分割実行したら細切れのカバレッジレポートが n個できちゃう → 結論: プロファイルの仕様で (無理やり)解決!
Slide 40
Slide 40 text
唯一の懸念点: カバレッジレポートどうしよう 結論: プロファイルの仕様で (無理やり)解決!
Slide 41
Slide 41 text
唯一の懸念点: カバレッジレポートどうしよう 結論: プロファイルの仕様 で(無理やり)解決!
Slide 42
Slide 42 text
唯一の懸念点: カバレッジレポートどうしよう 結論: プロファイルの仕様 で(無理やり)解決! カバレッジの計算モード set・count・atomicがある(割愛) ※ golang/go/src/cmd/cover/profile.goに該当の実装があります
Slide 43
Slide 43 text
各ファイルのカバレッジ情報 :.,. というフォーマットでカバレッジが大量にメモられている カバレッジの計算モード set・count・atomicがある(割愛) ※ golang/go/src/cmd/cover/profile.goに該当の実装があります 唯一の懸念点: カバレッジレポートどうしよう 結論: プロファイルの仕様 で(無理やり)解決!
Slide 44
Slide 44 text
そしてできあがった.yamlがこちら
Slide 45
Slide 45 text
そしてできあがった.yamlがこちら ※ 環境変数や serviceなど、この発表の範囲外と判断したために一部省略している箇所があります
Slide 46
Slide 46 text
そしてできあがった.yamlがこちら ※ 環境変数や serviceなど、この発表の範囲外と判断したために一部省略している箇所があります 例のID
Slide 47
Slide 47 text
例のID そしてできあがった.yamlがこちら ※ 環境変数や serviceなど、この発表の範囲外と判断したために一部省略している箇所があります テストを実行しプロファイルを出力
Slide 48
Slide 48 text
例のID そしてできあがった.yamlがこちら ※ 環境変数や serviceなど、この発表の範囲外と判断したために一部省略している箇所があります テストを実行しプロファイルを出力 名前にIDを含んだartifactを後続のジョブに遺す
Slide 49
Slide 49 text
例のID そしてできあがった.yamlがこちら ※ 環境変数や serviceなど、この発表の範囲外と判断したために一部省略している箇所があります テストを実行しプロファイルを出力 名前にIDを含んだartifactを後続のジョブに遺す ダウンロード
Slide 50
Slide 50 text
例のID そしてできあがった.yamlがこちら ※ 環境変数や serviceなど、この発表の範囲外と判断したために一部省略している箇所があります テストを実行しプロファイルを出力 名前にIDを含んだartifactを後続のジョブに遺す ダウンロード 1行目を直接書いて最終ファイルを作成 →各プロファイルの2行目以降をくっつける
Slide 51
Slide 51 text
例のID そしてできあがった.yamlがこちら ※ 環境変数や serviceなど、この発表の範囲外と判断したために一部省略している箇所があります テストを実行しプロファイルを出力 名前にIDを含んだartifactを後続のジョブに遺す ダウンロード レポート 作成
Slide 52
Slide 52 text
例のID そしてできあがった.yamlがこちら ※ 環境変数や serviceなど、この発表の範囲外と判断したために一部省略している箇所があります テストを実行しプロファイルを出力 名前にIDを含んだartifactを後続のジョブに遺す ダウンロード レポート 作成 最終レポート(HTML)を保存
Slide 53
Slide 53 text
例のID そしてできあがった.yamlがこちら ※ 環境変数や serviceなど、この発表の範囲外と判断したために一部省略している箇所があります テストを実行しプロファイルを出力 名前にIDを含んだartifactを後続のジョブに遺す ダウンロード レポート 作成 最終レポート(HTML)を保存 絶対もっといいやり方あるだろ
Slide 54
Slide 54 text
\ ありがとうございました! /