Go1.24時代の ユニットテスト品質向上
by
shotaro watanabe
×
Copy
Open
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Slide 1
Slide 1 text
Go1.24時代の ユニットテスト品質向上 Go Conference 2025 Sunday, 28 Sep 2025 2:00 pm - 2:20 pm 株式会社ジーニー 渡邉祥太朗 1
Slide 2
Slide 2 text
自己紹介 株式会社ジーニーでGoを書いている 渡邉 祥太朗(わたなべ しょうたろう)です GitHub: shotarowatanabe6 X: @5wee7 2
Slide 3
Slide 3 text
アジェンダ - ユニットテストが信頼できなかった話 - ユニットテストの改善例 - uber-go/mock - testing.T.Context() - 実装指針・文化醸成 3
Slide 4
Slide 4 text
ユニットテストが信頼できなかった話① - テストが外部APIやDBに依存し、不安定 - その箇所のテストを書くのをやめよう(実話) - 内部実装に依存し、些細な実装変更でテストが落ちる 4
Slide 5
Slide 5 text
ユニットテストが信頼できなかった話② - goroutineリークでCIが不安定 テスト1 OK テスト2 OK テスト4 OK or Fail テスト3 Leak テスト4で エラーが出ている...? テスト1〜3のどこかで リークしている...? 5
Slide 6
Slide 6 text
本日のゴール 信頼できる ユニットテスト 6
Slide 7
Slide 7 text
信頼できるユニットテスト - uber-go/mock - 生成したモックにより速く・安定して実行でき 些細な変更ではテストが落ちない - testing.T.Context() - goroutineリークのミスを軽減 7
Slide 8
Slide 8 text
uber-go/mock 8
Slide 9
Slide 9 text
uber-go/mock mockgen (以下略)コマンド または go generate ./… コマンド モックファイルが生成される 9 mockgen -source=db.go -destination=mock_db.go -package=db
Slide 10
Slide 10 text
uber-go/mock 外部依存を注入 key1にvalue1を返させる 10 mockDB.EXPECT().Get(“key1”) .Return(“value1”)
Slide 11
Slide 11 text
uber-go/mock 11
Slide 12
Slide 12 text
ユニットテストが信頼できなかった話①(再掲) - テストが外部APIやDBに依存し、不安定 - その箇所のテストを書くのをやめよう(実話) - 内部実装に依存し、些細な実装変更でテストが落ちる 12
Slide 13
Slide 13 text
uber-go/mock テストのために実装自体を考える必要がある問題 - DI (Dependency Injection) - 初期の実装コストが高い - コード量が増える - 小規模なアプリケーションでは過剰な場合もある VS 13
Slide 14
Slide 14 text
testing.T.Context() 14
Slide 15
Slide 15 text
testing.T.Context() 15 t.Cleanup() の実行前 または テスト終了時に contextをキャンセルしてくれる 1. contextを含むテストが書きやすく & 読みやすくなった 2. goroutineを扱う複数のテストを実行する場合に デバッグが楽になる
Slide 16
Slide 16 text
ユニットテストが信頼できなかった話②(再掲) - goroutineリークでCIが不安定 テスト1 OK テスト2 OK テスト4 OK or Fail テスト3 Leak テスト4で エラーが出ている...? テスト1〜3のどこかで リークしている...? 16
Slide 17
Slide 17 text
testing.T.Context() // 1. キャンセル可能なコンテキストを作成 ctx, cancel := context.WithCancel(context.Background()) // 2. テスト終了時にcancel()を呼びだす defer cancel() go doSomething(ctx) // 1. t.Context()を呼びだす ctx := t.Context() go doSomething(ctx) 17
Slide 18
Slide 18 text
testing.T.Context() goroutineを使用したworkerに対するテスト例 https://go.dev/play/p/NF2Xm209xZE?v=goprev gomockと組み合わせた例 https://go.dev/play/p/s_B_nPFlN9f?v=goprev https://github.com/shotarowatanabe6/testing_context_example 18
Slide 19
Slide 19 text
t.Context() でcontextを作成 t.Cleanupの前にcontextがキャンセルされる 19
Slide 20
Slide 20 text
GetData(any, “key1”)の際に以下を実 行 “key1” へのアクセスを httptest t.Context() を使用 contextがキャンセルされず正常に終了 20
Slide 21
Slide 21 text
GetData(any, “key1”)の際に以下を実 行 “key1” へのアクセスを httptest t.Context() を使用 contextがキャンセルされるまで待つ 21
Slide 22
Slide 22 text
実践指針・文化醸成 そうはいっても - 誰かが書いたコードにユニットテストを実装するのは大変 - ユニットテスト実装の時間が取れない - そもそもテストのために実装自体を疎結合にしないと 22
Slide 23
Slide 23 text
実践指針・文化醸成 - ユニットテストのTipsを集めてチームに共有 - httptest, miniredis, synctest, … - 自分で書いてコードレビューを依頼する(叩き台があると書きやすい ) - 勉強会で共有 - まずは新規実装にだけ テストを書き、体力を付ける - 既存のコードにテストを書くよりも精神的に楽 (良い事例があれば教えてください!) 23
Slide 24
Slide 24 text
Go1.24時代の ユニットテスト品質向上 Go Conference 2025 Sunday, 28 Sep 2025 2:00 pm - 2:20 pm 株式会社ジーニー 渡邉祥太朗 24