[インデックス 15213] ファイルの概要
このコミットは、Go言語のテストスイートにおいて、テストが失敗した場合に確実に非ゼロの終了コードを返すようにするための変更です。以前はエラーメッセージをprintln
で出力するだけでは、テストハーネスが失敗を適切に検出できない場合がありました。特に、新しいrun.go
ドライバーの導入により、以前の「ゴールデンファイル比較」のようなメカニズムが機能しなくなったため、テストの失敗を明示的に示すためにpanic
またはos.Exit(1)
を使用するように修正されました。これにより、自動テストシステムがテストの成否を正確に判断できるようになります。
コミット
- コミットインデックス: 15213
- コミットハッシュ: 052c942e20576f01f72d226d11aaf11e721009f3
- Author: Alan Donovan adonovan@google.com
- Date: Tue Feb 12 13:17:49 2013 -0500
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/052c942e20576f01f72d226d11aaf11e721009f3
元コミット内容
test: ensure all failing tests exit nonzero.
Previously merely printing an error would cause the golden
file comparison (in 'bash run') to fail, but that is no longer
the case with the new run.go driver.
R=iant
CC=golang-dev
https://golang.org/cl/7310087
変更の背景
この変更の主な背景には、Go言語のテスト実行環境の進化があります。コミットメッセージによると、以前はテストの失敗が単にエラーメッセージをprintln
で出力することで示されており、これが「ゴールデンファイル比較」(bash run
スクリプト内で実行されていたと推測される)によってテスト失敗として検出されていました。ゴールデンファイル比較とは、テストの出力があらかじめ定義された「ゴールデン」な出力と一致するかどうかを比較することで、テストの成否を判断する手法です。
しかし、新しいrun.go
ドライバーが導入されたことで、このゴールデンファイル比較のメカニズムが機能しなくなりました。つまり、テストが内部でエラーを検出してprintln
で出力しても、テスト実行プロセス自体は正常終了(終了コード0)してしまうため、自動テストシステムがその失敗を認識できなくなってしまったのです。
この問題を解決するため、テストが失敗した際には、プロセスが非ゼロの終了コードを返すように修正する必要がありました。これにより、テストハーネスやCI/CDパイプラインなどの外部システムが、テストの失敗を確実に検出できるようになります。
前提知識の解説
Go言語におけるエラー処理とプログラムの終了
Go言語では、プログラムの異常終了やエラーの通知に関して、主に以下のメカismsが用いられます。
-
println
/fmt.Printf
: これらは標準出力や標準エラー出力にメッセージを出力するための関数です。プログラムの実行フローを中断せず、終了コードにも影響を与えません。単に情報を表示する目的で使用されます。テストにおいて、エラーメッセージをprintln
で出力するだけでは、プログラム自体は正常終了するため、外部から見るとテストは成功したと判断されてしまう問題がありました。 -
panic
:panic
は、Goプログラムの通常の実行フローを中断し、パニック状態を引き起こします。パニックが発生すると、現在のゴルーチンは直ちに実行を停止し、遅延関数(defer
)が実行され、その後呼び出し元の関数へとパニックが伝播していきます。最終的に、recover
によってパニックが捕捉されない限り、プログラム全体がクラッシュし、非ゼロの終了コード(通常は2)で終了します。テストにおいては、テストケース内でpanic
を発生させることで、そのテストが失敗したことを明示的に示すことができます。 -
os.Exit(code int)
:os.Exit
関数は、Goプログラムを直ちに終了させ、指定された終了コード(code
)を返します。os.Exit(0)
は正常終了を意味し、os.Exit(1)
やその他の非ゼロの値は異常終了を意味します。panic
とは異なり、os.Exit
は遅延関数(defer
)を実行せず、スタックをアンワインドすることなくプログラムを終了させます。テストにおいて、特定の致命的なエラーが発生した場合に、プログラム全体を非ゼロの終了コードで終了させるために使用されます。
終了コード(Exit Code)の重要性
オペレーティングシステムにおいて、プログラムが終了する際に返す数値が「終了コード」または「終了ステータス」と呼ばれます。
- 0: 慣例的に、プログラムが正常に終了したことを示します。
- 非ゼロ(1以上): プログラムが何らかのエラーや異常な状態を検出して終了したことを示します。具体的な非ゼロの値は、エラーの種類を示すために使用されることがあります(例: 1は一般的なエラー、2はコマンドライン引数の誤りなど)。
自動テストシステム、ビルドシステム、CI/CDパイプラインなどは、実行されたプログラム(この場合はテストスイート)の終了コードをチェックすることで、その実行が成功したか失敗したかを判断します。テストスイートが失敗したにもかかわらず終了コード0を返してしまうと、これらのシステムはテストが成功したと誤認し、問題を見過ごしてしまう可能性があります。したがって、テストが失敗した際には必ず非ゼロの終了コードを返すことが、自動化された開発ワークフローにおいて極めて重要です。
技術的詳細
このコミットにおける技術的詳細は、Go言語のテストコード内でエラー検出時の挙動を、単なるメッセージ出力からプログラムの異常終了へと変更することに集約されます。
具体的には、多くのテストファイルで以下のような変更が行われています。
println("エラーメッセージ")
またはfmt.Printf("エラーメッセージ")
↓panic("エラーメッセージ")
またはpanic(fmt.Sprintf("エラーメッセージ", ...))
os.Exit(1)
この変更により、テストケース内で期待される条件が満たされなかった場合、即座にpanic
が発生するか、os.Exit(1)
が呼び出されます。
-
panic
の使用:panic
は、テスト関数内でアサーションが失敗した場合に特に有効です。panic
が発生すると、そのテスト関数は直ちに停止し、テストフレームワークによって捕捉され、テスト失敗として記録されます。最終的に、テストスイート全体が非ゼロの終了コードで終了します。panic
はスタックトレースを出力するため、どのテストのどの行で問題が発生したかを特定しやすくなります。これはデバッグにおいて非常に有用です。
-
os.Exit(1)
の使用:- 一部のテストでは、より直接的にプログラムを終了させるために
os.Exit(1)
が使用されています。これは、テストの失敗が非常に致命的であり、それ以上テストを続行する意味がない場合や、テストの実行環境自体に問題がある場合などに適しています。 os.Exit
はdefer
関数を実行しないため、リソースのクリーンアップが必要な場合には注意が必要です。しかし、テストの失敗を即座に外部に通知するという目的においては、非常に効果的です。
- 一部のテストでは、より直接的にプログラムを終了させるために
この変更は、Goのテストフレームワークがテスト結果をどのように集約し、最終的な終了コードを決定するかに依存しています。新しいrun.go
ドライバーは、個々のテストケースからのpanic
やos.Exit
を適切に処理し、テストスイート全体の終了コードに反映させるように設計されていると考えられます。これにより、テストの信頼性と自動化された検証プロセスの堅牢性が向上します。
コアとなるコードの変更箇所
このコミットでは、Go言語のテストファイル(test/
ディレクトリ以下の多数のファイル)において、テスト失敗時のエラー報告方法が変更されています。主な変更パターンは、エラーメッセージの出力(println
やfmt.Printf
)を、プログラムを非ゼロで終了させるpanic
またはos.Exit(1)
に置き換えることです。
以下に、いくつかの代表的な変更箇所を抜粋して示します。
test/alias1.go
--- a/test/alias1.go
+++ b/test/alias1.go
@@ -17,7 +17,7 @@ func main() {
case uint8:
// ok
default:
- println("byte != uint8")
+ panic("byte != uint8")
}
tx = uint8(2)
@@ -25,7 +25,7 @@ func main() {
case byte:
// ok
default:
- println("uint8 != byte")
+ panic("uint8 != byte")
}
rune32 := false
@@ -37,7 +37,7 @@ func main() {
// must be new code
rune32 = true
default:
- println("rune != int and rune != int32")
+ panic("rune != int and rune != int32")
}
if rune32 {
@@ -49,6 +49,6 @@ func main() {
case rune:
// ok
default:
- println("int (or int32) != rune")
+ panic("int (or int32) != rune")
}
}
test/bigalg.go
--- a/test/bigalg.go
+++ b/test/bigalg.go
@@ -15,18 +15,21 @@ type T struct {
d byte
}
-var a = []int{ 1, 2, 3 }
+var a = []int{1, 2, 3}
var NIL []int
func arraycmptest() {
if NIL != nil {
println("fail1:", NIL, "!= nil")
+ panic("bigalg")
}
if nil != NIL {
println("fail2: nil !=", NIL)
+ panic("bigalg")
}
if a == nil || nil == a {
println("fail3:", a, "== nil")
+ panic("bigalg")
}
}
test/copy.go
--- a/test/copy.go
+++ b/test/copy.go
@@ -132,6 +132,7 @@ func verify8(length, in, out, m int) {
n := ncopied(length, in, out)
if m != n {
fmt.Printf("count bad(%d %d %d): %d not %d\n", length, in, out, m, n)
+ os.Exit(1)
return
}
// before
test/map.go
fmt.Printf
をpanic(fmt.Sprintf(...))
に置き換える例が多く見られます。
--- a/test/map.go
+++ b/test/map.go
@@ -41,7 +41,7 @@ func testbasic() {
for i := 0; i < len(mlit); i++ {
s := string([]byte{byte(i) + '0'})
if mlit[s] != i {
- fmt.Printf("mlit[%s] = %d\n", s, mlit[s])
+ panic(fmt.Sprintf("mlit[%s] = %d\n", s, mlit[s]))
}
}
コアとなるコードの解説
これらの変更は、Goのテストが失敗した際に、その失敗を外部のテスト実行システムに確実に伝えるためのものです。
-
println
からpanic
への変更:println
は単にコンソールにメッセージを出力するだけで、プログラムの実行を中断しません。そのため、テストが失敗条件に合致しても、プログラム自体は正常終了し、テストハーネスはテストが成功したと誤認する可能性がありました。panic
を使用することで、テストが失敗条件に達した瞬間にプログラムの実行が中断され、非ゼロの終了コードで終了します。これにより、テストハーネスはテストが失敗したことを正確に検出できます。また、panic
はスタックトレースを出力するため、デバッグ情報も提供されます。
-
fmt.Printf
からpanic(fmt.Sprintf(...))
への変更:fmt.Printf
もprintln
と同様に、メッセージを出力するだけでプログラムの終了コードには影響しません。panic(fmt.Sprintf(...))
とすることで、フォーマットされたエラーメッセージをpanic
の引数として渡し、プログラムを異常終了させます。これにより、詳細なエラー情報を伴ってテスト失敗を通知できます。
-
os.Exit(1)
の追加:- 一部のテストでは、
fmt.Printf
でエラーメッセージを出力した後にos.Exit(1)
を呼び出すことで、明示的に非ゼロの終了コードでプログラムを終了させています。これは、panic
と同様にテスト失敗を外部に通知する効果がありますが、defer
関数が実行されないという点でpanic
とは異なります。テストの性質や、リソースクリーンアップの必要性に応じて使い分けられます。
- 一部のテストでは、
これらの変更は、Goのテストスイートがより堅牢になり、自動化されたテスト環境において信頼性の高い結果を提供する上で不可欠な改善です。テストの失敗が適切に報告されることで、開発者は問題を早期に発見し、修正することができます。
関連リンク
- Go CL 7310087: https://golang.org/cl/7310087 このコミットの変更リスト(Change List)へのリンクです。Goプロジェクトでは、Gitコミットの前にGerritなどのコードレビューシステムで変更が提案され、レビューされます。このCLリンクは、そのレビュープロセスにおける元の提案を示しています。
参考にした情報源リンク
- Go言語の
panic
とrecover
:- https://go.dev/blog/defer-panic-and-recover (Go公式ブログの
defer
,panic
,recover
に関する記事)
- https://go.dev/blog/defer-panic-and-recover (Go公式ブログの
- Go言語の
os.Exit
:- https://pkg.go.dev/os#Exit (Go標準ライブラリ
os
パッケージのExit
関数のドキュメント)
- https://pkg.go.dev/os#Exit (Go標準ライブラリ
- Go言語のテスト:
- https://go.dev/doc/code#Testing (Go公式ドキュメントのテストに関するセクション)
- シェルスクリプトの終了コード:
- https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html (Bashマニュアルの終了ステータスに関する説明)
- ゴールデンファイルテスト:
- https://martinfowler.com/bliki/GoldenMaster.html (Martin Fowler氏によるゴールデンマスターテストに関する説明)
- https://en.wikipedia.org/wiki/Golden_master_testing (Wikipediaのゴールデンマスターテストに関する記事)
[インデックス 15213] ファイルの概要
このコミットは、Go言語のテストスイートにおいて、テストが失敗した場合に確実に非ゼロの終了コードを返すようにするための変更です。以前はエラーメッセージをprintln
で出力するだけでは、テストハーネスが失敗を適切に検出できない場合がありました。特に、新しいrun.go
ドライバーの導入により、以前の「ゴールデンファイル比較」のようなメカニズムが機能しなくなったため、テストの失敗を明示的に示すためにpanic
またはos.Exit(1)
を使用するように修正されました。これにより、自動テストシステムがテストの成否を正確に判断できるようになります。
コミット
- コミットインデックス: 15213
- コミットハッシュ: 052c942e20576f01f72d226d11aaf11e721009f3
- Author: Alan Donovan adonovan@google.com
- Date: Tue Feb 12 13:17:49 2013 -0500
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/052c942e20576f01f72d226d11aaf11e721009f3
元コミット内容
test: ensure all failing tests exit nonzero.
Previously merely printing an error would cause the golden
file comparison (in 'bash run') to fail, but that is no longer
the case with the new run.go driver.
R=iant
CC=golang-dev
https://golang.org/cl/7310087
変更の背景
この変更の主な背景には、Go言語のテスト実行環境の進化があります。コミットメッセージによると、以前はテストの失敗が単にエラーメッセージをprintln
で出力することで示されており、これが「ゴールデンファイル比較」(bash run
スクリプト内で実行されていたと推測される)によってテスト失敗として検出されていました。ゴールデンファイル比較とは、テストの出力があらかじめ定義された「ゴールデン」な出力と一致するかどうかを比較することで、テストの成否を判断する手法です。
しかし、新しいrun.go
ドライバーが導入されたことで、このゴールデンファイル比較のメカニズムが機能しなくなりました。つまり、テストが内部でエラーを検出してprintln
で出力しても、テスト実行プロセス自体は正常終了(終了コード0)してしまうため、自動テストシステムがその失敗を認識できなくなってしまったのです。
この問題を解決するため、テストが失敗した際には、プロセスが非ゼロの終了コードを返すように修正する必要がありました。これにより、テストハーネスやCI/CDパイプラインなどの外部システムが、テストの失敗を確実に検出できるようになります。
前提知識の解説
Go言語におけるエラー処理とプログラムの終了
Go言語では、プログラムの異常終了やエラーの通知に関して、主に以下のメカニズムが用いられます。
-
println
/fmt.Printf
: これらは標準出力や標準エラー出力にメッセージを出力するための関数です。プログラムの実行フローを中断せず、終了コードにも影響を与えません。単に情報を表示する目的で使用されます。テストにおいて、エラーメッセージをprintln
で出力するだけでは、プログラム自体は正常終了するため、外部から見るとテストは成功したと判断されてしまう問題がありました。 -
panic
:panic
は、Goプログラムの通常の実行フローを中断し、パニック状態を引き起こします。パニックが発生すると、現在のゴルーチンは直ちに実行を停止し、遅延関数(defer
)が実行され、その後呼び出し元の関数へとパニックが伝播していきます。最終的に、recover
によってパニックが捕捉されない限り、プログラム全体がクラッシュし、非ゼロの終了コード(通常は2)で終了します。テストにおいては、テストケース内でpanic
を発生させることで、そのテストが失敗したことを明示的に示すことができます。 -
os.Exit(code int)
:os.Exit
関数は、Goプログラムを直ちに終了させ、指定された終了コード(code
)を返します。os.Exit(0)
は正常終了を意味し、os.Exit(1)
やその他の非ゼロの値は異常終了を意味します。panic
とは異なり、os.Exit
は遅延関数(defer
)を実行せず、スタックをアンワインドすることなくプログラムを終了させます。テストにおいて、特定の致命的なエラーが発生した場合に、プログラム全体を非ゼロの終了コードで終了させるために使用されます。
終了コード(Exit Code)の重要性
オペレーティングシステムにおいて、プログラムが終了する際に返す数値が「終了コード」または「終了ステータス」と呼ばれます。
- 0: 慣例的に、プログラムが正常に終了したことを示します。
- 非ゼロ(1以上): プログラムが何らかのエラーや異常な状態を検出して終了したことを示します。具体的な非ゼロの値は、エラーの種類を示すために使用されることがあります(例: 1は一般的なエラー、2はコマンドライン引数の誤りなど)。
自動テストシステム、ビルドシステム、CI/CDパイプラインなどは、実行されたプログラム(この場合はテストスイート)の終了コードをチェックすることで、その実行が成功したか失敗したかを判断します。テストスイートが失敗したにもかかわらず終了コード0を返してしまうと、これらのシステムはテストが成功したと誤認し、問題を見過ごしてしまう可能性があります。したがって、テストが失敗した際には必ず非ゼロの終了コードを返すことが、自動化された開発ワークフローにおいて極めて重要です。
技術的詳細
このコミットにおける技術的詳細は、Go言語のテストコード内でエラー検出時の挙動を、単なるメッセージ出力からプログラムの異常終了へと変更することに集約されます。
具体的には、多くのテストファイルで以下のような変更が行われています。
println("エラーメッセージ")
またはfmt.Printf("エラーメッセージ")
↓panic("エラーメッセージ")
またはpanic(fmt.Sprintf("エラーメッセージ", ...))
os.Exit(1)
この変更により、テストケース内で期待される条件が満たされなかった場合、即座にpanic
が発生するか、os.Exit(1)
が呼び出されます。
-
panic
の使用:panic
は、テスト関数内でアサーションが失敗した場合に特に有効です。panic
が発生すると、そのテスト関数は直ちに停止し、テストフレームワークによって捕捉され、テスト失敗として記録されます。最終的に、テストスイート全体が非ゼロの終了コードで終了します。panic
はスタックトレースを出力するため、どのテストのどの行で問題が発生したかを特定しやすくなります。これはデバッグにおいて非常に有用です。
-
os.Exit(1)
の使用:- 一部のテストでは、より直接的にプログラムを終了させるために
os.Exit(1)
が使用されています。これは、テストの失敗が非常に致命的であり、それ以上テストを続行する意味がない場合や、テストの実行環境自体に問題がある場合などに適しています。 os.Exit
はdefer
関数を実行しないため、リソースのクリーンアップが必要な場合には注意が必要です。しかし、テストの失敗を即座に外部に通知するという目的においては、非常に効果的です。
- 一部のテストでは、より直接的にプログラムを終了させるために
この変更は、Goのテストフレームワークがテスト結果をどのように集約し、最終的な終了コードを決定するかに依存しています。新しいrun.go
ドライバーは、個々のテストケースからのpanic
やos.Exit
を適切に処理し、テストスイート全体の終了コードに反映させるように設計されていると考えられます。これにより、テストの信頼性と自動化された検証プロセスの堅牢性が向上します。
コアとなるコードの変更箇所
このコミットでは、Go言語のテストファイル(test/
ディレクトリ以下の多数のファイル)において、テスト失敗時のエラー報告方法が変更されています。主な変更パターンは、エラーメッセージの出力(println
やfmt.Printf
)を、プログラムを非ゼロで終了させるpanic
またはos.Exit(1)
に置き換えることです。
以下に、いくつかの代表的な変更箇所を抜粋して示します。
test/alias1.go
--- a/test/alias1.go
+++ b/test/alias1.go
@@ -17,7 +17,7 @@ func main() {
case uint8:
// ok
default:
- println("byte != uint8")
+ panic("byte != uint8")
}
tx = uint8(2)
@@ -25,7 +25,7 @@ func main() {
case byte:
// ok
default:
- println("uint8 != byte")
+ panic("uint8 != byte")
}
rune32 := false
@@ -37,7 +37,7 @@ func main() {
// must be new code
rune32 = true
default:
- println("rune != int and rune != int32")
+ panic("rune != int and rune != int32")
}
if rune32 {
@@ -49,6 +49,6 @@ func main() {
case rune:
// ok
default:
- println("int (or int32) != rune")
+ panic("int (or int32) != rune")
}
}
test/bigalg.go
--- a/test/bigalg.go
+++ b/test/bigalg.go
@@ -15,18 +15,21 @@ type T struct {
d byte
}
-var a = []int{ 1, 2, 3 }
+var a = []int{1, 2, 3}
var NIL []int
func arraycmptest() {
if NIL != nil {
println("fail1:", NIL, "!= nil")
+ panic("bigalg")
}
if nil != NIL {
println("fail2: nil !=", NIL)
+ panic("bigalg")
}
if a == nil || nil == a {
println("fail3:", a, "== nil")
+ panic("bigalg")
}
}
test/copy.go
--- a/test/copy.go
+++ b/test/copy.go
@@ -132,6 +132,7 @@ func verify8(length, in, out, m int) {
n := ncopied(length, in, out)
if m != n {
fmt.Printf("count bad(%d %d %d): %d not %d\n", length, in, out, m, n)
+ os.Exit(1)
return
}
// before
test/map.go
fmt.Printf
をpanic(fmt.Sprintf(...))
に置き換える例が多く見られます。
--- a/test/map.go
+++ b/test/map.go
@@ -41,7 +41,7 @@ func testbasic() {
for i := 0; i < len(mlit); i++ {
s := string([]byte{byte(i) + '0'})
if mlit[s] != i {
- fmt.Printf("mlit[%s] = %d\n", s, mlit[s])
+ panic(fmt.Sprintf("mlit[%s] = %d\n", s, mlit[s]))
}
}
コアとなるコードの解説
これらの変更は、Goのテストが失敗した際に、その失敗を外部のテスト実行システムに確実に伝えるためのものです。
-
println
からpanic
への変更:println
は単にコンソールにメッセージを出力するだけで、プログラムの実行を中断しません。そのため、テストが失敗条件に合致しても、プログラム自体は正常終了し、テストハーネスはテストが成功したと誤認する可能性がありました。panic
を使用することで、テストが失敗条件に達した瞬間にプログラムの実行が中断され、非ゼロの終了コードで終了します。これにより、テストハーネスはテストが失敗したことを正確に検出できます。また、panic
はスタックトレースを出力するため、デバッグ情報も提供されます。
-
fmt.Printf
からpanic(fmt.Sprintf(...))
への変更:fmt.Printf
もprintln
と同様に、メッセージを出力するだけでプログラムの終了コードには影響しません。panic(fmt.Sprintf(...))
とすることで、フォーマットされたエラーメッセージをpanic
の引数として渡し、プログラムを異常終了させます。これにより、詳細なエラー情報を伴ってテスト失敗を通知できます。
-
os.Exit(1)
の追加:- 一部のテストでは、
fmt.Printf
でエラーメッセージを出力した後にos.Exit(1)
を呼び出すことで、明示的に非ゼロの終了コードでプログラムを終了させています。これは、panic
と同様にテスト失敗を外部に通知する効果がありますが、defer
関数が実行されないという点でpanic
とは異なります。テストの性質や、リソースクリーンアップの必要性に応じて使い分けられます。
- 一部のテストでは、
これらの変更は、Goのテストスイートがより堅牢になり、自動化されたテスト環境において信頼性の高い結果を提供する上で不可欠な改善です。テストの失敗が適切に報告されることで、開発者は問題を早期に発見し、修正することができます。
関連リンク
- Go CL 7310087: https://golang.org/cl/7310087 このコミットの変更リスト(Change List)へのリンクです。Goプロジェクトでは、Gitコミットの前にGerritなどのコードレビューシステムで変更が提案され、レビューされます。このCLリンクは、そのレビュープロセスにおける元の提案を示しています。
参考にした情報源リンク
- Go言語の
panic
とrecover
:- https://go.dev/blog/defer-panic-and-recover (Go公式ブログの
defer
,panic
,recover
に関する記事)
- https://go.dev/blog/defer-panic-and-recover (Go公式ブログの
- Go言語の
os.Exit
:- https://pkg.go.dev/os#Exit (Go標準ライブラリ
os
パッケージのExit
関数のドキュメント)
- https://pkg.go.dev/os#Exit (Go標準ライブラリ
- Go言語のテスト:
- https://go.dev/doc/code#Testing (Go公式ドキュメントのテストに関するセクション)
- シェルスクリプトの終了コード:
- https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html (Bashマニュアルの終了ステータスに関する説明)
- ゴールデンファイルテスト:
- https://martinfowler.com/bliki/GoldenMaster.html (Martin Fowler氏によるゴールデンマスターテストに関する説明)
- https://en.wikipedia.org/wiki/Golden_master_testing (Wikipediaのゴールデンマスターテストに関する記事)