[インデックス 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
で検索可能)