Go Wiki: テストの失敗
Go プロジェクトのテストで失敗が発生した場合、どうすればよいですか?
テストの目標
Go パッケージのテストを記述(および実行)する目標は、そのパッケージとその依存関係の動作について学ぶことです。
Go パッケージのテストの失敗は、以下の情報を与える可能性があります。
- パッケージまたはその依存関係の実装上の欠陥、
- パッケージ API に関する誤った仮定、
- テスト自体のバグ(タイミングに関する無効な仮定など)、
- 予期せぬ高リソース要件(RAM や CPU 時間など)、または
- 基盤となるプラットフォームのバグまたはテストインフラストラクチャの欠陥(エスカレーションまたは回避策が必要になる場合があります)。
場合によっては、テストの失敗の原因が明確でない場合があります。上記の複数の条件が原因である可能性があります。科学実験を繰り返すのと同様に、テストを複数回失敗させることで、特定の失敗パターンからより多くの情報を得られる場合があります。
ただし、テストが新しい情報を何も伝えずに失敗する場合、そのテストはその目的を果たしていません。
テストの失敗を見つける
テストの失敗は、通常、以下から気づかれます。
- Go ビルドダッシュボード、特に ビルダー トリアージ 中;
- 保留中の変更に対する TryBot または SlowBot の失敗;
- Go プロジェクトリポジトリ内で作業している場合、またはユーザー独自のモジュールで(たとえば)`go test all` の一部として、特定のパッケージで `go test` を実行している場合;
- または、ソースからインストールする際、または コントリビュートされた変更をテストする際に、`all.bash` または `all.bat` を実行している場合。
テストの失敗のトリアージ
失敗に気づいたら、それを*トリアージ*する必要があります。トリアージの目標は、以下を特定することです。
- 失敗からの情報は新しいですか?
- 失敗からの新しい情報を分析するのに最適な人物は誰ですか?
新しい情報の特定
まず、未解決の issue で、失敗したテストの名前やエラーテキストのその他の独特の断片(エラーコードなど)などの重要な詳細を検索します。
既存の issue が見つかった場合は、まず issue の議論を確認して、失敗がすでに修正されているかどうか、および失敗からの情報が関連する新しい情報を提供しているかどうかを確認します。もしそうであれば、詳細を*コメント*します。
- テストしていた Go のバージョン (`go version`) を記述する
- テストの実行方法と場所(例:
- `go env` の出力
- マシンと OS の構成
- ネットワークの構成とステータス
- 失敗を再現できるかどうか、およびその頻度。
理想的には、完全なテストログを添付またはリンクします(可能であれば `<details>` ブロック内)。
既存の issue が見つからない場合は、新しい issue を作成します。
issue の作成
将来の報告者が issue を検索できるように、テストの名前とそのログ出力の独特の部分を含め、テストログを十分に貼り付けます。(テストログが長い場合(たとえば、大きなゴルーチンダンプが含まれている場合)、短い抜粋を投稿するか、完全な失敗メッセージを `<details>` ブロックに囲むことを検討してください。)
`fetchlogs` および `greplogs` ツールを使用して、ビルドダッシュボードで同様の失敗を検索できます。
# download recent logs
fetchlogs -n 1024 -repo all
# search logs for some regexp describing the failure message
greplogs -l -e $FAILURE_REGEXP
失敗が特定のパッケージに固有と思われる場合は、https://dev.golang.org/owners を参照してそのパッケージのメンテナーを見つけ、issue でメンションしてください。(パッケージのオーナーがリストされていない場合は、https://cs.opensource.google/go でパッケージの最近の履歴を確認するか、関連するオーナーを特定するのを手伝ってくれる人にエスカレーションし、オーナーテーブル をあなたが学んだことで更新することを検討してください!)
失敗が特定の `GOOS` または `GOARCH` に固有と思われる場合は、対応する GOOS および/または GOARCH ラベルで issue にラベルを付け、@golang/port-maintainers の関連するサブチームを issue でメンションしてください。
失敗が少なくとも 1 つの ファーストクラスポート に影響を与えると思われる場合は、issue を現在のリリースのマイルストーンに追加し、`release-blocker` ラベルを付けます。そうでない場合は、issue を `Backlog` マイルストーンに追加します。
失敗が特定のビルダーに固有と思われる場合(ネットワーク接続の問題、システムアップデートが必要なプラットフォームのバグなど)、`x/build/dashboard/builders.go` を参照してそのビルダーのメンテナーを見つけ、issue でメンションしてください。(明示的なメンテナーがリストされていないビルダーの場合は、代わりに @golang/release チームをメンションしてください。)
テストの失敗に対処する
テストの失敗について issue が作成されたら、関連するパッケージ、ポート、および/またはビルダーのメンテナーは、テストの失敗から収集された情報を調べて、以下のいずれか 1 つ以上を実行することで、どのように*対処*するかを決定する必要があります。
- 問題を引き起こしたと考えられるコードまたはテストインフラストラクチャへの変更を*元に戻す*、
- 失敗の根本原因を*修正*する(または回避策を適用する)、
- issue の更新を購読したり、より多くのテストを実行したりすることで、より多くの情報を*収集*する、
- 依存関係、プラットフォーム、またはテストインフラストラクチャの根本的な欠陥を*報告*する、および/または
- 影響を受けるプラットフォームで失敗をスキップする(またはそれらのプラットフォームを壊れているとマークする)ことによって、失敗の*優先順位を下げ*、issue を将来または `Backlog` マイルストーンに移動し、`release-blocker` ラベルを削除する。
メンテナーがテストの失敗の優先順位を下げることを決定した場合、*テストの追加の失敗は有用な新しい情報を提供しない*と判断します。その時点で、テストはその目的を果たさなくなり、メンテナーは通常、`testenv.SkipFlaky` または `t.Skipf` を呼び出すことによって、失敗を抑制する必要があります。
テストの失敗をスキップする
`testenv.SkipFlaky` の呼び出しを追加する場合の目標は、新しい情報を提供しない失敗モードを排除しながら、テストの価値を可能な限り維持することです。
-
観察された失敗がテストのいくつかの可能な失敗モードの 1 つに過ぎない場合は、その失敗モードについてのみテストをスキップします。
- たとえば、エラーが常に `syscall.ECONNRESET` のような特定のものである場合は、`errors.Is` を使用してその特定のエラーを確認します。
-
失敗が特定の `GOOS` および/または `GOARCH` のすべてのバージョンに影響すると考えられる場合、または影響を受けるバージョンを特定できない場合は、`runtime.GOOS` および/または `runtime.GOARCH` に対してチェックを行い、影響を受けるプラットフォームのみをスキップします。
-
失敗がプラットフォームの*特定のバージョン*のバグが原因である場合は、`testenv.Builder` または `GO_BUILDER_NAME` 環境変数に基づいてテストをスキップします。(外部の Go ユーザーでテストが失敗した場合、彼らはプラットフォームの影響を受けないバージョンにアップグレードするオプションがあります。また、バグが存在することを知るためにテストの失敗を確認する必要があります!)
- また、ユーザーとコントリビューターがバグを認識して失敗を抑制するために設定できる別の環境変数の追加も検討してください。
ビルダーまたはポートを壊れているとマークする
プラットフォームのバグまたはコアカウントロールパッケージ(`os`、`net`、`runtime` など)のバグは、非常に多くのテストに影響を与える可能性があり、失敗をスキップすることができないか、コンパイル時またはリンク時に失敗として現れる可能性があります。このようなバグが発生した場合、オプションはより制限されます。変更を元に戻したり、根本原因を修正または回避したりすることができず、より多くの情報を収集する必要がない場合は、*ビルダーまたはプラットフォーム全体*を壊れているとマークすることによってのみ、失敗の優先順位を下げることができます。
ビルダーを壊れているとマークするには、`x/build/dashboard/builders.go` でその構成を編集し、`KnownIssue` フィールドに issue を追加します。既知の問題があるビルダーは、通常、ダッシュボードのトリアージ中にスキップされることに注意してください。
ファーストクラスポート の壊れたビルダーは、ビルダーを修正するか、影響を受けるバージョンのプラットフォームのサポートをドロップするかの決定が下されるまで、既知の問題に `release-blocker` のラベルが付けられている必要があります。
セカンダリポートのすべてのビルダーが壊れている場合、ポート自体が壊れていると見なされる場合があります。ディスカッション#53060 は、壊れたセカンダリポートをどのように処理するかの問題を解決することを目的としています。
このコンテンツは Go Wiki の一部です。