Slide 1

Slide 1 text

Goのテスト ケースは逐次、テストは並列 2024/08/23 #めぐろLT 株式会社HRBrain 岡田 光博

Slide 2

Slide 2 text

2 AGENDA ● 自己紹介 ● テストが「CIでは通る」が「ローカルで通らない」 ● 実装しているテストの例 ● 問題のあったテストの例 ● 何が問題だったか ● 具体的な実装の例 ● まとめ

Slide 3

Slide 3 text

自己紹介

Slide 4

Slide 4 text

4 自己紹介 ● 岡田光博(みつ) ● 現在は、新規プロダクトでバックエンド!(4月〜) ○ もともとは、フロントエンド(インターン) ● 趣味 ○ カメラ ○ 音楽(最近は、R&B) ○ 食べ飲み歩く(三茶の混混ってところおすすめ) ● アイスブレイク

Slide 5

Slide 5 text

アイスブレイク 先週の台風でぷち怖かった話

Slide 6

Slide 6 text

6 アイスブレイク ● Timesでつぶやくと・・・

Slide 7

Slide 7 text

7 アイスブレイク ● 確認漏れでした。

Slide 8

Slide 8 text

Goのテスト 「CIでは通る」が「ローカルで通らない」

Slide 9

Slide 9 text

9 「CIでは通る」が「ローカルで通らない」 こんなエラーが・・・。 === RUN Test_Domain_XXX fatal error: sync: unlock of unlocked mutex goroutine 1 [running]:

Slide 10

Slide 10 text

10 「CIでは通る」が「ローカルで通らない」 mutexエラー ↓ 複数のゴルーチンから同じメモリ領域にアクセスしようとして、エラーが出るのだろうかと考 えて調査を進めていた

Slide 11

Slide 11 text

11 実装しているテストの例 ● Test_XXX ● fields ● tests(ケース) ● t.Runでコールバック

Slide 12

Slide 12 text

12 問題のあったテストの例 ● monkey.Patch() ← Returnの値をPatchするために使っている箇所があった。 ● Test_XXX ● fields ● tests(ケース) ● t.Runでコールバック

Slide 13

Slide 13 text

13 何が問題だったか ● defer は、関数の最後に実行される ● patch() と unpatch() は内部でmutexのlockを使っている ● テストケースは逐次実行されるが、 Test_XXXは、並列に実行される ● Test_XXX() とその他の Testが一緒に走り、unlock 前に次の lock をかけようとした ↓ ● 本来、よりスコープの狭いt.Run内のコールバック関数で patch() の unpatch()(mutex のlock解除)を実行しないといけない

Slide 14

Slide 14 text

14 具体的な実装の例 ● Test_XXXの下ではなく、t.Runのコールバックの中でdeferで解除処理をする。

Slide 15

Slide 15 text

● Goのテストは、並列に実行される ● Goのテストケースは、逐次実行される ● defer は、関数の最後に実行される ● lockの解除タイミングを誤ると処理がぶつかることがある。 15 まとめ

Slide 16

Slide 16 text

ご清聴ありがとうございました!