メインコンテンツへスキップ

Go Proposal Weekly Digest

Go言語のproposal更新を毎週お届け

#75047active

testing: add goroutine labels to tests

新規提案

要約

AIによる要約であり、誤りを含む場合があります。

概要

テスト実行時に各goroutineへtest.nameなどのpprofラベルを自動付与し、複数のテストが同時実行されている際に「どのgoroutineがどのテストに属するか」を容易に特定できるようにする提案です。

ステータス変更

(新規)active
2026年8月19日の週次proposal reviewミーティングにて、Issueがactiveカラムに追加され、今後review meetingで継続的に議論されることが決定しました("added to minutes")。これは正式な承認・却下の判断ではなく、proposal reviewの俎上に載った段階を意味します。提案者のdfinkel氏は2026年1月に「proposal reviewのキューに見当たらない」と催促のコメントを残しており、その後review対象として取り込まれた形です。

技術的背景

現状の問題点

テストがタイムアウトした場合、実行中の複数goroutineのうちどれがどのテストに対応するかを特定するのが困難でした。近年、タイムアウト時に「実行中のテスト一覧」を表示する改善が入りましたが、goroutineのスタックトレースとテスト名を紐付ける手段はありませんでした。パニックやタイムアウト時のトレースバックを見ても、どのgoroutineがどのテスト関数の実行中だったのか判別できないという課題です。

提案された解決策

testingパッケージが各テスト・ベンチマーク・ファズテストの実行に対してruntime/pprofのgoroutineラベル(pprof.Do相当の仕組み)を自動的に設定します。具体的なラベル案は以下の通りです。

  • test.name: t.Name()と同じフルテスト名
  • test.iter: -count指定時、2回目以降の実行回数(初回は省略し視覚的ノイズを減らす)
  • bench.name / bench.run.iter: ベンチマーク(サブベンチマーク含む)向け
  • fuzz.name: 直接実行されるファズテスト(-fuzz FuzzFoo
  • fuzz.corpus.name / fuzz.corpus.iter: コーパス(シード・testdata)ベースの通常テストとして実行されるファズテスト
    関連して、既に着地済みのCL(https://go.dev/cl/694119, https://go.dev/cl/751580)により、Go 1.26以降トレースバック出力自体にgoroutineラベルを表示する機能(GODEBUG=tracebacklabels=1、あるいはgo.modで1.27以上を指定した場合はデフォルト有効)も並行して整備されています。

これによって何ができるようになるか

  • タイムアウト・デッドロック調査: テストがハングした際、goroutine dumpに表示される各goroutineのラベルを見るだけで、どのテストがどこまで進んで止まっているか一目で分かる
  • パニック時のデバッグ: パニックで自動出力されるトレースバックにtest.nametest.iterが付くことで、-countで複数回実行した際に「何回目の実行で失敗したか」を即座に把握できる
  • CPUプロファイリング: -test.cpuprofile-cpuprofileで取得したプロファイルはpprofのprotobuf形式で既にgoroutineラベルを保持しているため、pproftag.*フィルタ機能を使い、どのテスト・ベンチマークがCPU時間を多く消費しているかを詳細に絞り込める

コード例

// Before: タイムアウト時のgoroutineダンプにはgoroutine番号とスタックのみで
// どのテストの実行かが分からない
// goroutine 36 [running]:
//     ...
// After: testingパッケージが自動でラベルを設定するため、追加コード不要で
// goroutine dumpに test.name / test.iter が表示される
// goroutine 36 gp=0x33789cd803c0 m=0 mp=0x6d37e0 [running] {test.iter: 2, test.name: TestWithPanic}:
//     panic({0x690ff8?, 0x550230?})
//     .../runtime/panic.go:879 +0x16f

議論のハイライト

  • 提案者のdfinkel氏はこの機能を、関連issue #23458(トレースバックへのgoroutineラベル追加)の実装(CL 694119)を進める中でのモチベーションとして着想したと説明しており、両issueは密接に関連しています
  • glycerine氏はより広い発想として、パニック時にローカル変数の値もスタックダンプに表示できないかと提案しましたが、dfinkel氏はセグフォルト後のポインタ参照が二次クラッシュを招く危険性やスコープ拡大への懸念から、本提案の範囲外(スコープクリープを避けたい)と明確に線引きしています
  • ラベルのキー名(test.iterなど)について提案者自身が「もっと良い名前があるか」を未解決の論点として挙げており、bench.run.iterのようにrunを挟むのはb.Loopb.Nによるループの曖昧さを解消するためだと説明されています
  • 初回実行(0回目)ではtest.iter/fuzz.corpus.iterラベルを付与しない設計とし、-count未指定または1の一般的なケースでの表示ノイズを減らす配慮がなされています
  • 実装はCL 740301(runtime/pprof: Move goroutine labeling to internal)とCL 740320(testing: goroutine labels with name & iteration)の2本に分割されており、レビュー段階に入っています

関連リンク