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