Go Wiki: テストの失敗
Go プロジェクトのテストで失敗に気づいた場合、どうすべきでしょうか?
テストの目標
Go パッケージのテストを作成(および実行)する目的は、そのパッケージとその依存関係の動作について知ることです。
Go パッケージのテストの失敗は、以下に関する情報を提供する可能性があります。
- パッケージまたはその依存関係の実装上の欠陥、
- パッケージ API に関する誤った前提、
- テスト自体のバグ(タイミングに関する無効な前提など)、
- 予想外に高いリソース要件(RAM や CPU 時間など)、または
- 基盤となるプラットフォームのバグ、またはテストインフラストラクチャの欠陥(エスカレートまたは回避する必要がある場合があります)。
場合によっては、テストの失敗の原因が明確ではないことがあります。上記の条件の_複数_が原因である可能性もあります。科学実験を繰り返すように、テストを複数回失敗させることで、特定の失敗パターンからより多くの情報が得られることがあります。
ただし、テストが新しい情報を提供せずに失敗した場合、そのテストは目的を果たしていません。
テストの失敗を見つける
テストの失敗は、通常、以下から認識されます。
- Go ビルドダッシュボード、特にビルダーのトリアージ中。
- 保留中の変更に対する TryBot またはSlowBot の失敗。
- Go プロジェクトのリポジトリ内、またはユーザー自身のモジュール内の (たとえば)
go test allの一部として、特定のパッケージまたは複数のパッケージに対してgo testを実行する。 - または、ソースからインストールする場合、または貢献された変更をテストする場合に
all.bashまたはall.batを実行する。
テストの失敗のトリアージ
失敗に気づいたら、それを_トリアージ_する必要があります。トリアージの目標は、以下を特定することです。
- 失敗からの情報は新しいものか?
- 失敗からの新しい情報を分析するのに最も適しているのは誰か?
新しい情報の特定
未解決の課題で、失敗したテストの名前やエラーテキストのその他の特徴的な断片(エラーコードなど)といった主要な詳細を検索することから始めます。
既存の課題が見つかった場合は、まず課題の議論を確認して、失敗がすでに修正されているか、および失敗からの情報が関連する新しい情報を提供するかどうかを確認します。もしそうであれば、詳細を付けて_コメントしてください_。
- テストしていた Go のバージョン (
go version) を記述する - テストの実行方法と場所(例:)
go envの出力- お使いのマシンと OS の設定
- ネットワーク設定と状況
- 再現できるかどうか、および再現頻度。
理想的には、完全なテストログを添付またはリンクしてください(おそらく <details> ブロック内)。
既存の課題が見つからない場合は、新しい課題を立ててください。
課題の提起
テストの名前やログ出力の distinctive な部分を含め、将来の報告者が課題を検索できるように十分なテストログを貼り付けます。(テストログが長い場合 — たとえば、大きなゴルーチンのダンプが含まれる場合 — 短い抜粋を投稿するか、完全な失敗メッセージを <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 を参照してそのパッケージのメンテナーを見つけ、課題で彼らに言及してください。(パッケージのオーナーがリストされていない場合は、https://cs.opensource.google/go でパッケージの最近の履歴を確認するか、関連するオーナーを特定できる人にエスカレートしてください — そして、学んだことをもとにオーナーテーブルを更新することを検討してください!)
失敗が特定の GOOS または GOARCH に固有であると思われる場合は、対応する GOOS および/または GOARCH ラベルで課題にラベル付けし、課題で@golang/port-maintainers の関連サブチームに言及してください。
失敗が少なくとも 1 つのファーストクラスポートに影響を与えていると思われる場合は、課題を現在のリリース目標に追加し、release-blocker のラベルを付けます。そうでない場合は、課題を Backlog 目標に追加します。
失敗が特定のビルダーに固有のようであれば(ネットワーク接続の問題やシステムアップデートが必要なプラットフォームのバグなど)、x/build/dashboard/builders.go を参照してそのビルダーのメンテナーを見つけ、課題で彼らに言及してください。(明示的なメンテナーがリストされていないビルダーの場合、代わりに@golang/release チームに言及してください。)
テストの失敗に対処する
テストの失敗について課題が提出されたら、関連するパッケージ、ポート、および/またはビルダーのメンテナーは、テストの失敗から得られた情報を調査し、以下の1つ以上を行うことで、それに_対処_する方法を決定する必要があります。
- 問題を引き起こしたと思われるコードまたはテストインフラストラクチャへの変更を_元に戻す_、
- 失敗の根本原因を_修正_する(または回避策を適用する)、
- 課題の更新を購読したり、さらにテストを実行したりして、より多くの情報を_収集_する、
- 依存関係、プラットフォーム、またはテストインフラストラクチャにおける根本的な欠陥を_報告_する、および/または
- 影響を受けるプラットフォームでの失敗をスキップする(またはそれらのプラットフォームを壊れているとマークする)ことで、失敗の_優先順位を下げる_。その後、課題を将来のまたは
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 フィールドに課題を追加します。既知の課題があるビルダーは、通常、ダッシュボードのトリアージ中にスキップされることに注意してください。
ファーストクラスポートの壊れたビルダーは、その既知の課題に release-blocker のラベルが付けられ、ビルダーを修正するか、影響を受けるプラットフォームのバージョンのサポートを中止するかを決定するまで保留となります。
セカンダリポートのすべてのビルダーが壊れている場合、ポート自体が壊れていると見なされる可能性があります。議論 #53060 は、壊れたセカンダリポートをどのように処理すべきかという問題を解決することを目指しています。
このコンテンツはGo Wikiの一部です。