[インデックス 13739] ファイルの概要
このコミットは、Go言語のドキュメントに含まれるサンプルプログラムのテスト方法を改善し、特にWindows環境でのテスト実行を test/run.go
スクリプトを使用するように変更するものです。これにより、Windows上でのテストの互換性と信頼性が向上します。また、特定のプログラム(cgo関連や go1.go
)が現状ではテストできないことを明示し、その理由をコメントで補足しています。
コミット
- コミットハッシュ:
5b7562dd6fe04aa3e827c66ee7ac7b57b6afa667
- 作者: Shenghou Ma minux.ma@gmail.com
- コミット日時: Mon Sep 3 03:49:03 2012 +0800
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/5b7562dd6fe04aa3e827c66ee7ac7b57b6afa667
元コミット内容
doc/progs: use test/run.go for testing on Windows
cgo[1-4].go, go1.go couldn't be tested now
(cgo[1-4].go can only be tested when cgo is enabled, go1.go
contain a list of filenames in the current directory)
R=golang-dev, alex.brainman, rsc
CC=golang-dev
https://golang.org/cl/6218048
変更の背景
この変更の主な背景は、Go言語のドキュメントに含まれるサンプルコード(doc/progs
ディレクトリ内のGoプログラム)のテストプロセスを、特にWindows環境において改善することにあります。
当時のGoプロジェクトでは、テストの実行方法がプラットフォームによって異なる場合がありました。特にWindows環境では、Unix系システムで一般的に使用されるシェルスクリプト(例: run.bash
)が直接実行できないため、テストの自動化や一貫性に課題がありました。
このコミット以前は、doc/progs
内のサンプルコードのテストがWindowsで適切に機能していなかったか、あるいは手動での介入が必要だった可能性があります。cgo[1-4].go
のようなCgoを使用するプログラムや、カレントディレクトリのファイルリストを出力する go1.go
のようなプログラムは、その性質上、特定の環境設定(Cgoの有効化)や実行時のコンテキスト(ファイルリストの比較)に依存するため、一般的なテストフレームワークでは扱いにくい側面がありました。
このコミットは、test/run.go
というGo言語で書かれたテストヘルパースクリプトを導入することで、Windowsを含む様々なプラットフォームで doc/progs
内のサンプルコードをより堅牢かつ自動的にテストできるようにすることを目的としています。これにより、ドキュメントのコード例が常に正しく動作することを保証し、開発者がGo言語の機能を学習する際の信頼性を高めることができます。
前提知識の解説
このコミットを理解するためには、以下のGo言語および関連技術に関する知識が必要です。
- Go言語のテストフレームワーク: Go言語には標準で
testing
パッケージが用意されており、go test
コマンドを使ってテストを実行します。しかし、このコミットで扱われているのは、Goのソースコードリポジトリ内の特定のテストヘルパースクリプト (test/run.go
) や、ドキュメントのサンプルコードを検証するためのカスタムなテストメカニズムです。 test/run.go
: これはGo言語の公式リポジトリ内に存在する、Goプログラムのテスト実行を補助するためのユーティリティスクリプトです。通常のgo test
とは異なり、特定のディレクトリ内のGoファイルをコンパイル・実行し、その出力や挙動を検証するような、より柔軟なテストシナリオに対応するために使用されます。特に、Goのビルドシステムやテストインフラストラクチャの一部として機能します。- Cgo: CgoはGoプログラムからC言語のコードを呼び出すためのGoの機能です。Cgoを使用するプログラムは、Cコンパイラやリンカがシステムにインストールされている必要があり、通常のGoプログラムよりもビルド・実行環境の依存関係が複雑になります。そのため、Cgoプログラムのテストは、Cgoが有効な環境でのみ実行可能です。
Makefile
:Makefile
はmake
コマンドによって実行されるビルド自動化ツールです。Goプロジェクトでは、テストの実行、コードの生成、ドキュメントのビルドなど、様々なタスクを自動化するために使用されます。このコミットでは、doc/Makefile
がドキュメントのサンプルコードのテストに関連するターゲットを持つことが示唆されています。*.bat
ファイル (Windows Batch Script): Windows環境でコマンドを実行するためのスクリプトファイルです。Unix系OSのシェルスクリプト (.sh
や.bash
) に相当します。src/run.bat
は、Goのテストスイート全体を実行するためのWindows固有のスクリプトであり、このコミットではdoc/progs
のテストをtest/run.go
経由で実行するように変更されています。- ドキュメントのサンプルコードのテスト: Goの公式ドキュメント(特に
effective_go.html
など)には、Go言語の機能を示すためのコード例が埋め込まれています。これらのコード例が常に正しく動作することを保証するために、自動テストが実行されます。このコミットは、そのテストメカニズムの一部を修正しています。 // skip
,// cmpout
,// compile
,// run
ディレクティブ: Goのテストシステムやドキュメント生成システムで使用される、特別なコメントディレクティブです。これらは、Goのソースファイルの上部に記述され、そのファイルがどのようにテストされるべきか、あるいはドキュメントにどのように組み込まれるべきかを指示します。// skip
: そのファイルをテストから除外します。// cmpout
: プログラムの実行結果を、対応する.out
ファイルの内容と比較して検証します。// compile
: プログラムがコンパイルできることを検証します(実行はしません)。// run
: プログラムを実行し、その実行がエラーなく完了することを検証します。
技術的詳細
このコミットは、Go言語のドキュメント (doc/
) 内のサンプルプログラムのテスト方法に複数の変更を加えています。
doc/progs
ディレクトリ内のGoプログラムへのディレクティブ追加:cgo1.go
からcgo4.go
には// skip
ディレクティブが追加されました。これは、これらのファイルがCgoを必要とし、現在のテスト環境(特にWindowsでのtest/run.go
を使用したテスト)ではCgoが有効になっていないため、テストをスキップすることを示します。コミットメッセージにも「cgo[1-4].go can only be tested when cgo is enabled」と明記されています。defer.go
,defer2.go
,eff_bytesize.go
,eff_sequence.go
,image_package1.go
からimage_package6.go
,interface2.go
,json2.go
には// cmpout
ディレクティブが追加されました。これは、これらのプログラムを実行し、その標準出力が対応する.out
ファイル(例:defer.out
)の内容と一致することを検証するテストであることを示します。defer.out
,defer2.out
,eff_bytesize.out
,eff_sequence.out
,image_package1.out
からimage_package6.out
,interface2.out
,json2.out
といった新しい.out
ファイルが追加されました。これらは、// cmpout
ディレクティブを持つGoプログラムの期待される出力を含んでいます。eff_qr.go
,error.go
からerror4.go
,gobs1.go
,gobs2.go
,image_draw.go
,interface.go
,json3.go
,json5.go
,slices.go
,timeout1.go
,timeout2.go
には// compile
ディレクティブが追加されました。これは、これらのプログラムがコンパイル可能であることを検証するテストであることを示します。json1.go
,json4.go
には// run
ディレクティブが追加されました。これは、これらのプログラムが実行可能であることを検証するテストであることを示します。go1.go
には// compile
ディレクティブと、// this file will output a list of filenames in cwd, not suitable for cmpout
というコメントが追加されました。これは、このプログラムがカレントディレクトリのファイルリストを出力するため、出力比較テストには適さないことを示唆しています。
doc/Makefile
の変更:compare
という新しいmake
ターゲットが追加されました。このターゲットは、RAWHTML
変数で指定されたHTMLファイル(Goドキュメントの生HTML)をgodoc -url
コマンドで処理し、その出力と元のHTMLファイルをdiff -u
で比較します。これは、ドキュメントのHTMLがgodoc
によって正しく生成されることを検証するためのものです。
doc/progs/update.bash
の新規追加:- このシェルスクリプトは、
doc/progs
ディレクトリ内のGoプログラムのテスト結果を自動的に生成するためのものです。 - 既存の
.out
,.rej
,.orig
ファイルなどを削除します。 // cmpout
ディレクティブを持つGoファイルを見つけ、go run
で実行し、その出力を対応する.out
ファイルにリダイレクトします。これにより、期待される出力ファイルが自動的に更新されます。これは、テストの基準となる出力を簡単に更新するためのユーティリティです。
- このシェルスクリプトは、
src/run.bat
の変更:- Windows環境でのテスト実行スクリプトである
src/run.bat
に、doc\progs
ディレクトリのテストを実行するための行が追加されました。 - 具体的には、
go run %GOROOT%\test\run.go - ..\doc\progs
というコマンドが追加され、doc\progs
ディレクトリ内のGoプログラムがtest/run.go
を介してテストされるようになりました。 - また、
..\misc\cgo\stdio
のテストもtest/run.go
を使用するように変更されています。 - 以前はコメントアウトされていた
:: TODO(brainman): disabled, because it fails with: mkdir C:\\Users\\ADMINI~1\\AppData\\Local\\Temp\\2.....\\go\\misc\\cgo\\: The filename or extension is too long.
というCgoテストに関するコメントが残されており、Windowsでのパスの長さ制限による問題がまだ存在することを示唆しています。
- Windows環境でのテスト実行スクリプトである
これらの変更により、Goドキュメントのサンプルコードのテストがより自動化され、特にWindows環境でのテストの実行可能性と信頼性が向上しました。
コアとなるコードの変更箇所
このコミットにおけるコアとなるコードの変更箇所は以下の通りです。
doc/progs/*.go
ファイル群:- 多数のGoプログラムファイルに、
// skip
,// cmpout
,// compile
,// run
といった特別なコメントディレクティブが追加されました。 - 例:
doc/progs/cgo1.go
に+// skip
が追加。 - 例:
doc/progs/defer.go
に+// cmpout
が追加。 - 例:
doc/progs/eff_qr.go
に+// compile
が追加。 - 例:
doc/progs/json1.go
に+// run
が追加。
- 多数のGoプログラムファイルに、
doc/progs/*.out
ファイル群:// cmpout
ディレクティブを持つGoプログラムに対応する、期待される出力を含む新しい.out
ファイルが多数追加されました。- 例:
doc/progs/defer.out
(新規ファイル) - 例:
doc/progs/defer2.out
(新規ファイル)
doc/Makefile
:compare
という新しいmake
ターゲットが追加され、godoc
の出力と既存のHTMLファイルを比較するロジックが記述されました。
doc/progs/update.bash
:// cmpout
ディレクティブを持つGoプログラムの.out
ファイルを自動生成・更新するためのシェルスクリプトが新規追加されました。
src/run.bat
:- Windows環境でのテスト実行スクリプトに、
doc\progs
ディレクトリのテストをtest/run.go
を使用して実行するコマンドが追加されました。
- Windows環境でのテスト実行スクリプトに、
コアとなるコードの解説
doc/progs/*.go
ファイルへのディレクティブ追加
Goのテストシステムは、Goソースファイルの先頭に記述された特定のコメント行を特別なディレクティブとして解釈します。このコミットでは、doc/progs
ディレクトリ内の各サンプルプログラムに対して、そのプログラムがどのようにテストされるべきかを指示するディレクティブが追加されました。
-
// skip
:// skip // Copyright 2012 The Go Authors. All rights reserved. // ...
cgo[1-4].go
に追加されました。これは、これらのファイルがCgoに依存しており、現在のテスト環境ではCgoが有効になっていないため、テストをスキップするように指示します。これにより、Cgoが利用できない環境でのテスト失敗を防ぎます。 -
// cmpout
:// cmpout // Copyright 2011 The Go Authors. All rights reserved. // ...
defer.go
,defer2.go
など多数のファイルに追加されました。このディレクティブは、test/run.go
スクリプトに対して、このGoプログラムを実行し、その標準出力が同じベース名を持つ.out
ファイル(例:defer.out
)の内容と完全に一致するかどうかを検証するように指示します。これは、プログラムの出力が期待通りであることを保証するための回帰テストとして機能します。 -
// compile
:// compile // Copyright 2009 The Go Authors. All rights reserved. // ...
eff_qr.go
,error.go
など多数のファイルに追加されました。このディレクティブは、test/run.go
スクリプトに対して、このGoプログラムがエラーなくコンパイルできることを検証するように指示します。これは、構文エラーや型エラーがないことを確認するための基本的な健全性チェックです。 -
// run
:// run // Copyright 2012 The Go Authors. All rights reserved. // ...
json1.go
,json4.go
に追加されました。このディレクティブは、test/run.go
スクリプトに対して、このGoプログラムを実行し、実行時にパニックやランタイムエラーが発生しないことを検証するように指示します。出力の比較は行いませんが、プログラムが正常に終了することを確認します。
doc/progs/*.out
ファイルの新規追加
// cmpout
ディレクティブが追加されたGoプログラムに対応して、そのプログラムの期待される出力を格納する .out
ファイルが新規作成されました。例えば、doc/progs/defer.go
に // cmpout
が追加された場合、doc/progs/defer.out
が作成され、defer.go
を実行した際の期待される出力が記述されます。これらのファイルは、test/run.go
が出力比較テストを実行する際の基準となります。
doc/Makefile
の compare
ターゲット
compare:
for i in $(RAWHTML); do \
godoc -url /doc/$${i/.rawhtml/.html} | diff -u $$i -; \
done
この新しい compare
ターゲットは、GoドキュメントのHTMLファイルが godoc
コマンドによって正しく生成されることを検証するためのものです。RAWHTML
変数に含まれる各生HTMLファイル (.rawhtml
) に対して、godoc -url
コマンドを使ってそのHTMLを再生成し、元のファイルと diff -u
で比較します。これにより、ドキュメントの生成プロセスが意図した通りに機能しているか、あるいは意図しない変更がないかを確認できます。
doc/progs/update.bash
スクリプト
#!/usr/bin/env bash
# ...
set -e
rm -f *.out *.rej *.orig [568].out
for i in *.go; do
if grep -q '^// cmpout$' $i; then
echo $i
go run $i &> ${i/.go/.out}
fi
done
このシェルスクリプトは、doc/progs
ディレクトリ内の // cmpout
ディレクティブを持つGoプログラムの期待される出力ファイル (.out
ファイル) を自動的に生成または更新するためのユーティリティです。
set -e
: コマンドが失敗した場合にスクリプトを即座に終了させます。rm -f ...
: 以前のテスト実行で生成された可能性のある不要なファイルを削除し、クリーンな状態にします。for i in *.go; do ... done
: ディレクトリ内のすべてのGoファイルに対してループします。if grep -q '^// cmpout$' $i; then ... fi
: 現在のGoファイルが// cmpout
ディレクティブを含んでいるかどうかをチェックします。go run $i &> ${i/.go/.out}
:// cmpout
ディレクティブを持つGoファイルを実行し、その標準出力と標準エラー出力を、対応する.out
ファイルにリダイレクトして保存します。これにより、プログラムの現在の出力が.out
ファイルに書き込まれ、テストの基準が更新されます。これは、プログラムの挙動が変更された際に、手動で.out
ファイルを更新する手間を省くための非常に便利なツールです。
src/run.bat
の変更
echo # ..\doc\progs
go run %GOROOT%\test\run.go - ..\doc\progs
if errorlevel 1 goto fail
echo.
Windows環境でのGoのテストスイート全体を実行する src/run.bat
に、doc\progs
ディレクトリのテストを実行する行が追加されました。
go run %GOROOT%\test\run.go - ..\doc\progs
コマンドは、test/run.go
スクリプトをGoプログラムとして実行し、引数として ..\doc\progs
を渡します。これにより、test/run.go
は doc/progs
ディレクトリ内のGoプログラムを検出し、それぞれのディレクティブ(// skip
, // cmpout
など)に従ってテストを実行します。
if errorlevel 1 goto fail
は、コマンドの実行結果がエラーであった場合に、スクリプトを fail
ラベルにジャンプさせるWindowsバッチスクリプトの一般的なエラーハンドリングです。
これらの変更は、Goのドキュメントに含まれるサンプルコードの品質を維持し、特にWindows環境でのテストの自動化と信頼性を高める上で重要な役割を果たしています。
関連リンク
- Go CL (Change List): https://golang.org/cl/6218048
参考にした情報源リンク
- 上記のGo CLのリンク
- Go言語の公式ドキュメント (特に
go test
コマンドやcgo
に関するセクション) - Go言語のソースコードリポジトリ (
test/run.go
やdoc/
ディレクトリの構造) - Gitの
diff
コマンドの出力形式に関する一般的な知識 Makefile
およびbash
スクリプトに関する一般的な知識- Windowsバッチスクリプトに関する一般的な知識
- Go言語の
effective_go.html
ドキュメント (コミットで変更されたファイル) godoc
コマンドの機能