[インデックス 12710] ファイルの概要
このコミットは、Go言語のテストインフラストラクチャにおける重要な改善を導入しています。具体的には、テストファイル内で特定のテストをスキップするための新しいディレクティブ // skip を導入し、既存のテストファイルの一部をこの新しい形式に移行しています。これにより、テストの管理と実行がより明確かつ効率的になります。
コミット
commit e2662835b8dd3ca4aa69997afe3774467a677df8
Author: Shenghou Ma <minux.ma@gmail.com>
Date: Thu Mar 22 02:14:44 2012 +0800
test: use testlib in a few more cases
Introduce a new skip cmd.
R=golang-dev, bradfitz, iant, iant
CC=golang-dev
https://golang.org/cl/5868048
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/e2662835b8dd3ca4aa69997afe3774467a677df8
元コミット内容
test: use testlib in a few more cases
Introduce a new skip cmd.
R=golang-dev, bradfitz, iant, iant
CC=golang-dev
https://golang.org/cl/5868048
変更の背景
Go言語のテストスイートは、コンパイラ、ランタイム、標準ライブラリの正確性を保証するために非常に広範です。初期のGoのテストフレームワークでは、テストファイルの先頭にコメント形式でテストの期待される動作や実行方法を記述する慣習がありました。例えば、// true はテストが成功することを期待することを示し、複雑なシェルコマンドが記述されることもありました。
しかし、このような記述方法は、テストの意図を明確にする上で曖昧さを含んだり、テストランナーが解釈するロジックが複雑になったりする可能性がありました。特に、特定の条件下でテストをスキップしたい場合、そのための明確なメカニズムが不足していました。
このコミットの背景には、テストインフラストラクチャをより堅牢で、理解しやすく、保守しやすいものにするという目的があります。// skip コマンドの導入は、テストの実行を明示的に制御し、テストランナーが不要なテストを実行しないようにするための、よりクリーンな方法を提供します。これにより、テストスイート全体の実行時間を短縮し、開発者がテストの意図をより迅速に把握できるようになります。
また、test/fixedbugs/bug223.go の変更に見られるように、以前はシェルコマンドで表現されていたエラーチェックのロジックが // errorcheck および // ERROR ディレクティブに置き換えられています。これは、テストの期待値をGoのテストフレームワーク内でより直接的に表現する方向への移行を示しており、テストの可読性と移植性を向上させる狙いがあります。
前提知識の解説
このコミットを理解するためには、以下のGo言語のテストに関する基本的な知識が必要です。
- Go言語のテストフレームワーク: Go言語は標準で
testingパッケージを提供しており、go testコマンドを通じてテストを実行します。しかし、このコミットが対象としているのは、Goプロジェクト自体のコンパイラやランタイムのテストであり、これらはtestingパッケージとは異なる、より低レベルなカスタムテストハーネス (test/run.goなど) を使用しています。 test/run.go: これはGo言語のソースコードリポジトリ内のカスタムテストランナーです。Goのコンパイラやランタイムのテストは、通常のgo testコマンドでは実行できない特殊なケースが多く、このrun.goがそれらのテストをオーケストレーションする役割を担っています。テストファイルの先頭に記述された特殊なコメント(ディレクティブ)を解釈し、それに基づいてテストのコンパイル、ビルド、実行、または特定のチェックを行います。test/testlib: これはシェルスクリプトのライブラリであり、test/run.goがテストを実行する際に利用するヘルパー関数や環境設定を提供します。例えば、コンパイルや実行の際に共通して使用されるパスやフラグなどが定義されています。- テストディレクティブ: Goのテストファイル(特にコンパイラやランタイムのテスト)の先頭には、
//で始まる特殊なコメントが記述されることがあります。これらはテストランナー (test/run.go) に対する指示であり、テストの実行方法や期待される結果を定義します。例えば、// trueはテストが成功することを期待し、// errorcheckはコンパイルエラーをチェックすることを示します。
技術的詳細
このコミットの技術的な核心は、test/run.go と test/testlib の変更、そして既存のテストファイルへの新しい // skip ディレクティブの適用にあります。
-
test/run.goの変更:test構造体にactionフィールドがあり、これがテストの実行アクション("compile","build","run","errorcheck"など)を決定します。このコミットでは、このactionフィールドが取りうる値に"skip"が追加されました。run()関数内のロジックが更新され、テストファイルの先頭から読み取られたディレクティブが"skip"であった場合、t.actionを"skip"に設定し、即座にreturnするようになりました。これにより、// skipとマークされたテストは、それ以降のコンパイルや実行のステップに進むことなく、テストランナーによってスキップされます。test/run.go自体の先頭のディレクティブも// #ignoreから// skipに変更されています。これは、run.go自体がテストとして実行されるべきではないことを示唆しています。
-
test/testlibの変更:skip()という新しいシェル関数が追加されました。この関数は単にtrueを返します。これは、test/run.goがskipアクションを処理する際に、testlib内で対応するコマンドが存在することを保証するためのプレースホルダー、または将来的な拡張のための準備と考えられます。
-
既存テストファイルの変更:
- 多くのテストファイル(例:
test/cmplxdivide.c,test/cmplxdivide1.go,test/ddd2.goなど)の先頭のディレクティブが、// trueやその他の複雑なシェルコマンドから// skipに変更されました。これは、これらのテストが特定の条件下で実行される必要がない、あるいは一時的に無効化されていることを示します。 - 特筆すべきは
test/fixedbugs/bug223.goの変更です。このファイルでは、以前は// (! $G $D/$F.go) | grep 'initialization loop' >/dev/null || echo BUG: bug223という複雑なシェルコマンドが記述されていました。これは、コンパイル時に「initialization loop」というエラーメッセージが出力されることを期待するものでした。このコミットでは、これが// errorcheckと// ERROR "initialization loop"に変更されています。// errorcheckは、テストランナーに対して、このファイルがコンパイルエラーをチェックするためのものであることを指示します。// ERROR "initialization loop"は、その行で指定された正規表現に一致するエラーメッセージがコンパイラから出力されることを期待することを示します。 この変更は、テストの期待値をシェルコマンドに依存するのではなく、Goのテストフレームワーク内でより宣言的に表現する方向への移行を明確に示しています。これにより、テストの可読性が向上し、異なる環境でのテスト実行の信頼性が高まります。
- 多くのテストファイル(例:
コアとなるコードの変更箇所
test/run.go
--- a/test/run.go
+++ b/test/run.go
@@ -1,4 +1,4 @@
-// #ignore
+// skip
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
@@ -172,7 +172,7 @@ type test struct {
donec chan bool // closed when done
src string
- action string // "compile", "build", "run", "errorcheck"
+ action string // "compile", "build", "run", "errorcheck", "skip"
tempDir string
err error
@@ -253,6 +253,9 @@ func (t *test) run() {
fallthrough
case "compile", "build", "run", "errorcheck":
t.action = action
+ case "skip":
+ t.action = "skip"
+ return
default:
t.err = skipError("skipped; unknown pattern: " + action)
t.action = "??"
test/testlib
--- a/test/testlib
+++ b/test/testlib
@@ -38,3 +38,7 @@ cmpout() {
errorcheck() {
errchk $G -e $D/$F.go
}
+
+skip() {
+ true
+}
test/fixedbugs/bug223.go
--- a/test/fixedbugs/bug223.go
+++ b/test/fixedbugs/bug223.go
@@ -1,4 +1,4 @@
-// (! $G $D/$F.go) | grep 'initialization loop' >/dev/null || echo BUG: bug223
+// errorcheck
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
@@ -18,4 +18,4 @@ func f() {
}
}
-var m = map[string]F{"f": f}
+var m = map[string]F{"f": f} // ERROR "initialization loop"
コアとなるコードの解説
test/run.go の変更点
-
test構造体のactionフィールド:action string // "compile", "build", "run", "errorcheck", "skip"この行は、test構造体のactionフィールドが取りうる値に"skip"が追加されたことを示しています。これは、テストランナーがテストを「スキップ」するという新しい動作を認識できるようになったことを意味します。 -
run()メソッド内のcase "skip":case "skip": t.action = "skip" returnこれは、
test/run.goの中核的な変更です。テストファイルの先頭に// skipディレクティブが検出された場合、run()メソッドはこのcase "skip"ブロックに入ります。t.action = "skip": 現在のテストの実行アクションを"skip"に設定します。return: これが最も重要です。このreturnステートメントにより、テストのコンパイル、ビルド、実行、エラーチェックなどの後続の処理が一切行われずに、run()メソッドが即座に終了します。これにより、// skipとマークされたテストは効率的にスキップされます。
-
ファイル先頭のディレクティブ変更:
// #ignoreから// skipへの変更は、test/run.go自体がテストとして実行されるべきではないことを、新しいより明確なskipディレクティブで表現しています。
test/testlib の変更点
skip() {
true
}
testlib に skip() という新しいシェル関数が追加されました。この関数は単に true を返します。これは、test/run.go が skip アクションを処理する際に、testlib 内で対応するコマンドが存在することを保証するためのものです。Goのテストハーネスは、テストディレクティブに対応するシェル関数を testlib から呼び出すことがあるため、この定義は互換性や将来的な拡張のために重要です。
test/fixedbugs/bug223.go の変更点
- // (! $G $D/$F.go) | grep 'initialization loop' >/dev/null || echo BUG: bug223
+ // errorcheck
...
- var m = map[string]F{"f": f}
+ var m = map[string]F{"f": f} // ERROR "initialization loop"
この変更は、テストの期待値の表現方法が改善されたことを示しています。
- 以前の行は、シェルコマンドを使用して、コンパイラが「initialization loop」という文字列を含むエラーを出力するかどうかをチェックしていました。これは外部コマンド (
grep) に依存し、プラットフォーム間の互換性やエラーメッセージの厳密なマッチングに課題がありました。 - 新しい
// errorcheckディレクティブは、このファイルがコンパイルエラーをチェックするためのものであることをtest/run.goに直接伝えます。 // ERROR "initialization loop"は、特定のコード行で期待されるエラーメッセージの正規表現パターンを直接指定します。これにより、テストランナーはコンパイラの出力とこのパターンを比較し、より正確かつGoのテストフレームワーク内で完結した形でエラーチェックを実行できます。これは、テストの堅牢性と可読性を大幅に向上させます。
これらの変更により、Goのテストインフラストラクチャは、テストのスキップをより明示的に行えるようになり、またエラーチェックのメカニズムもよりGoネイティブで宣言的な方法に進化しました。
関連リンク
- Go言語の公式リポジトリ: https://github.com/golang/go
- Gerrit Change-Id:
5868048(Goプロジェクトのコードレビューシステム)
参考にした情報源リンク
- Go言語のテストに関する公式ドキュメント (当時のものに直接アクセスすることは難しいですが、現在のドキュメントも参考になります): https://go.dev/doc/code#testing
- Go言語のソースコード内の
testディレクトリの構造と慣習 (コミット当時の状況を推測する上で重要): https://github.com/golang/go/tree/master/test - Go言語のGerritコードレビューシステム: https://go-review.googlesource.com/ (コミットメッセージに記載されているCL番号
5868048で検索可能)