この記事はsyumai Advent Calendar 2024の3日目の記事です。
火曜なので、本日は「Go」がテーマとなります。
(*testing.T).Context()とは
(*testing.T).Context()
は、以下のProposalでAcceptされた、Goのテストで使用できる新しいメソッドです。
このメソッドから返却されるContextは、t.Cleanup()
によって登録されたクリーンアップ関数が呼び出される直前にキャンセルされます。
Proposalの最終的なAPIは以下の通りです。
// Context returns a context that's cancelled just before // [T.Cleanup]-registered functions are called. // // Cleanup functions can wait for any resources // that shut down on Context.Done before the test completes. func (t *T) Context() context.Context
実装は既にmaster branchにマージされていて、現在Go 1.24のマイルストーンでのリリースが見込まれています。 testing.Tへの追加と言いましたが、実際には、testing.T / B / Fで共通のインタフェースであるtesting.TBへ追加が行われたようです。
使い方
ProposalのDescriptionに記載されているのは、次のような使い方です。
func TestFoo(t *testing.T) { // 1. Contextを取得 ctx := t.Context() // 2. WaitGroupを作成 var wg sync.WaitGroup // 3. テストの完了時のクリーンアップ処理でwg.Waitを呼ぶように指定 t.Cleanup(wg.Wait) // 4. WaitGroupにテスト内で使用する処理を登録 wg.Add(1) go func() { defer wg.Done() // 5. テストのクリーンアップ処理の直前まで待つContextを渡す doSomething(ctx) }() }
このコードを読むだけではあまりイメージしにくいかもしれませんが、本機能のメリットは「テストの完了まで待ってくれるContextが入手できる」点にあります。
上記の doSomething
関数をもっと具体化してみましょう。