[インデックス 16917] ファイルの概要
このコミットは、Go言語のドキュメントに含まれる「codewalk」のサンプルコードに対するテストを追加するものです。具体的には、doc/codewalk/run
という新しいスクリプトが追加され、既存の src/run.bash
からこの新しいテストスクリプトが呼び出されるように変更されています。これにより、Goのcodewalkドキュメント内のコード例が正しく動作することを保証するための自動テストが導入されました。
コミット
commit fc32bfa9cc4bec0eeed7193f96ea5ffc2c32ca49
Author: Andrew Gerrand <adg@golang.org>
Date: Tue Jul 30 09:42:53 2013 +1000
doc/codewalk: test source code
Fixes #2648.
R=golang-dev, r
CC=golang-dev
https://golang.org/cl/11331043
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/fc32bfa9cc4bec0eeed7193f96ea5ffc2c32ca49
元コミット内容
doc/codewalk: test source code
Fixes #2648.
R=golang-dev, r
CC=golang-dev
https://golang.org/cl/11331043
変更の背景
このコミットの主な背景は、Go言語の公式ドキュメントの一部である「codewalk」に含まれるコード例の品質と信頼性を向上させることにあります。codewalkは、Goの特定の機能や概念をステップバイステップで解説するために、実行可能なコード例を豊富に含んでいます。しかし、これらのコード例が時間の経過とともにGo言語の進化やAPIの変更によって古くなったり、意図せず壊れたりする可能性があります。
コミットメッセージにある Fixes #2648
は、この変更が特定の課題(Issue 2648)を解決することを示しています。当時のGoプロジェクトの慣習として、ドキュメント内のコード例がテストされていないために、それらが壊れている可能性があるという問題意識がありました。このコミットは、ドキュメントの正確性とユーザー体験を保証するために、これらのコード例を自動テストの対象とすることを目的としています。
前提知識の解説
Go Codewalks (コードウォーク)
Go Codewalksは、Go言語の特定のトピックや機能について、インタラクティブなチュートリアル形式で学ぶためのドキュメントです。これらは通常、Goのウェブサイト(go.dev/tour
や go.dev/doc/codewalk
など)で提供されており、コードスニペットとそれに対応する説明が組み合わされています。ユーザーはブラウザ上でコードを実行し、その結果を確認しながら学習を進めることができます。
Codewalkの重要な特徴は、単なる静的なドキュメントではなく、実際に動作するGoのコードが含まれている点です。これにより、ユーザーは理論だけでなく実践を通じてGoを学ぶことができます。しかし、この「動作するコード」という性質上、Go言語のバージョンアップやライブラリの変更によって、コードが期待通りに動作しなくなるリスクが常に存在します。
go run
コマンド
go run
コマンドは、Goのソースファイルをコンパイルし、すぐに実行するためのコマンドです。開発中にGoプログラムを素早くテストしたり、小さなスクリプトを実行したりする際によく使用されます。このコマンドは、一時的な実行可能ファイルを生成し、実行後に削除します。
シェルスクリプト (bash
)
このコミットでは、bash
シェルスクリプトが使用されています。bash
はUnix系OSで広く使われているコマンドラインシェルであり、スクリプト言語としても機能します。ファイル操作、プログラムの実行、条件分岐、ループなど、様々なタスクを自動化するために利用されます。
#!/usr/bin/env bash
: シバン(Shebang)と呼ばれ、このスクリプトがbash
インタプリタによって実行されるべきであることをシステムに伝えます。set -e
: このコマンドは、スクリプト内で実行されるコマンドのいずれかが非ゼロの終了ステータス(エラー)を返した場合、スクリプトが即座に終了するように設定します。これにより、エラーが発生した際にスクリプトが予期せぬ動作を続けることを防ぎ、テストの失敗を確実に検出できます。go run <file.go>
: 指定されたGoファイルをコンパイルして実行します。grep <pattern> > /dev/null
:grep
コマンドは、入力から指定されたパターンを検索します。> /dev/null
は、grep
の標準出力を破棄し、画面に何も表示しないようにします。grep
はパターンが見つかった場合は終了ステータス0を、見つからなかった場合は非ゼロを返します。この特性を利用して、特定の出力が期待通りに生成されたかをテストします。|| fail <message>
: 論理OR演算子です。左側のコマンド(grep
など)が失敗(非ゼロの終了ステータスを返す)した場合にのみ、右側のfail
関数が実行されます。fail
関数はエラーメッセージを表示し、スクリプトを終了させます。go build -o /dev/null <file.go>
: 指定されたGoファイルをコンパイルしますが、-o /dev/null
オプションにより、生成された実行可能ファイルを/dev/null
に出力(破棄)します。これは、実行可能ファイルが正しくビルドできるかどうかのテストに利用されます。
技術的詳細
このコミットの技術的な核心は、Go codewalkのコード例を自動的にテストするための新しいメカニズムの導入です。
-
doc/codewalk/run
スクリプトの追加:- この新しいシェルスクリプトは、Go codewalks内の特定のGoプログラム(
markov.go
,pig.go
,urlpoll.go
など)を対象としています。 - 各Goプログラムに対して、
go run
コマンドを使用して実行し、その出力が期待されるパターンと一致するかどうかをgrep
とリダイレクト (> /dev/null
) を組み合わせて検証します。 markov.go
の例では、echo foo | go run markov.go | grep foo > /dev/null
というパイプラインを使用しています。これは、markov.go
が標準入力から何かを読み込み、それを標準出力にエコーバックするような動作を期待していることを示唆しています。grep foo
でfoo
が出力に含まれることを確認しています。pig.go
の例では、ゲームのシミュレーション結果のような特定の文字列 (Wins, losses staying at k = 100: 210/990 (21.2%), 780/990 (78.8%)
) が出力されることを期待しています。urlpoll.go
の例では、ネットワークを使用するプログラムであるため、実際に実行するのではなく、go build -o /dev/null urlpoll.go
を使用して、単にコンパイルが成功するかどうかだけをテストしています。これは、テスト環境で外部ネットワークアクセスを必要としないようにするための賢明な判断です。fail
関数は、テストが失敗した場合に統一されたエラーメッセージを出力し、スクリプトを終了させるためのヘルパー関数です。
- この新しいシェルスクリプトは、Go codewalks内の特定のGoプログラム(
-
src/run.bash
の変更:src/run.bash
は、Goプロジェクト全体のテストスイートやビルドプロセスの一部として実行されるメインのシェルスクリプトです。- 以前は、
doc/codewalk
ディレクトリ内のpig.go
とurlpoll.go
を個別にビルドし、その後生成されたバイナリを削除していました。これは、単にビルドが通ることを確認するだけの限定的なテストでした。 - このコミットにより、これらの個別のビルドコマンドは削除され、代わりに新しく追加された
doc/codewalk/run
スクリプトが呼び出されるようになりました (time ./run || exit 1
)。 time
コマンドは、スクリプトの実行時間を計測するために使用されます。|| exit 1
は、./run
スクリプトが非ゼロの終了ステータス(エラー)を返した場合に、src/run.bash
スクリプト全体もエラーで終了するようにします。
この変更により、GoのCI/CDパイプラインの一部として、codewalkのコード例が定期的に自動テストされるようになり、ドキュメントの品質と正確性が維持されるようになりました。
コアとなるコードの変更箇所
doc/codewalk/run
(新規追加)
--- /dev/null
+++ b/doc/codewalk/run
@@ -0,0 +1,21 @@
+#!/usr/bin/env bash
+# Copyright 2013 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+set -e
+
+function fail {
+ echo FAIL: doc/codewalk/$1
+ exit 1
+}
+
+# markov.xml
+echo foo | go run markov.go | grep foo > /dev/null || fail markov
+
+# functions.xml
+go run pig.go | grep 'Wins, losses staying at k = 100: 210/990 (21.2%), 780/990 (78.8%)' > /dev/null || fail pig
+
+# sharemem.xml: only build the example, as it uses the network
+go build -o /dev/null urlpoll.go || fail urlpoll
src/run.bash
(変更)
--- a/src/run.bash
+++ b/src/run.bash
@@ -152,10 +152,7 @@ make clean || exit 1
) || exit $?\n \n (xcd ../doc/codewalk\n-# TODO: test these too.\n-go build pig.go || exit 1\n-go build urlpoll.go || exit 1\n-rm -f pig urlpoll\n+time ./run || exit 1\n ) || exit $?\n \n echo
コアとなるコードの解説
doc/codewalk/run
このスクリプトは、Go codewalksの各コード例をテストするための独立した実行ファイルとして機能します。
set -e
: これが最も重要な設定の一つで、スクリプト内の任意のコマンドが失敗した場合(非ゼロの終了コードを返した場合)に、スクリプト全体の実行を即座に停止させます。これにより、テストの失敗が確実に検出され、後続のテストが実行されることなくエラーが報告されます。function fail { ... }
: テストが失敗した際に呼び出されるユーティリティ関数です。引数としてテストの名前を受け取り、FAIL: doc/codewalk/<テスト名>
という形式でエラーメッセージを標準出力に出力し、exit 1
でスクリプトをエラー終了させます。echo foo | go run markov.go | grep foo > /dev/null || fail markov
:markov.go
というGoプログラムを実行し、その標準入力にfoo
を渡します。markov.go
の標準出力をgrep foo
にパイプし、出力にfoo
が含まれているかを確認します。> /dev/null
でgrep
の出力を破棄し、grep
の終了ステータスのみを利用します。|| fail markov
は、grep
が失敗した場合(foo
が見つからなかった場合)にfail markov
を呼び出し、テスト失敗としてスクリプトを終了させます。
go run pig.go | grep '...' > /dev/null || fail pig
:pig.go
というGoプログラムを実行し、その標準出力に特定の文字列が含まれているかを確認します。これは、pig.go
がゲームのシミュレーション結果のような固定の出力を生成することを期待していることを示しています。
go build -o /dev/null urlpoll.go || fail urlpoll
:urlpoll.go
というGoプログラムをコンパイルします。-o /dev/null
オプションにより、コンパイルされた実行可能ファイルはディスクに保存されず、即座に破棄されます。これは、プログラムがネットワークアクセスを必要とするため、実際の実行は行わず、単にコンパイルが成功するかどうかだけをテストしていることを意味します。コンパイルエラーがあれば、go build
は非ゼロの終了ステータスを返し、fail urlpoll
が呼び出されます。
src/run.bash
このスクリプトは、Goプロジェクトのトップレベルのテストスクリプトであり、様々なサブシステムのテストをオーケストレーションします。
(xcd ../doc/codewalk ...)
:xcd
は、Goプロジェクトの内部で定義されているディレクトリ変更とエラーチェックを組み合わせたヘルパー関数です。このブロックは、doc/codewalk
ディレクトリに移動し、その中でテストを実行することを意味します。- # TODO: test these too.
以下の3行 (go build pig.go || exit 1
,go build urlpoll.go || exit 1
,rm -f pig urlpoll
) は削除されました。これらは以前、codewalkのGoプログラムがビルドできることを確認するだけの限定的なテストでした。+ time ./run || exit 1
: 削除された行の代わりに、新しく追加されたdoc/codewalk/run
スクリプトが実行されるようになりました。time
コマンドは、./run
スクリプトの実行にかかる時間を計測し、その結果を標準エラー出力に表示します。これは、テストのパフォーマンスを監視するのに役立ちます。|| exit 1
は、./run
スクリプトがエラーで終了した場合(つまり、codewalkのテストのいずれかが失敗した場合)に、src/run.bash
スクリプト全体もエラーで終了するようにします。これにより、CIシステムなどがテストの失敗を検出しやすくなります。
この変更により、Goのビルドおよびテストプロセスにcodewalkのコード例の自動テストが統合され、ドキュメントのコード例が常に最新かつ動作可能であることが保証されるようになりました。
関連リンク
- GitHubコミット: https://github.com/golang/go/commit/fc32bfa9cc4bec0eeed7193f96ea5ffc2c32ca49
- Gerrit Change-Id (CL): https://golang.org/cl/11331043
- Go Issue 2648 (当時のGoプロジェクトのIssueトラッカー): https://code.google.com/p/go/issues/detail?id=2648 (注: 2013年当時のGoのIssueトラッカーはGoogle Code上にありました。現在はGitHub Issuesに移行しています。)
参考にした情報源リンク
- Go言語公式ドキュメント (Codewalksの概念理解のため): https://go.dev/doc/
- Go言語ツアー (Codewalksのインタラクティブな性質の理解のため): https://go.dev/tour/
- Bashスクリプトの基本的な構文とコマンド (
set -e
,grep
, パイプなど) に関する一般的な知識。 - Go言語の
go run
およびgo build
コマンドに関する公式ドキュメントまたはヘルプ。 - GoプロジェクトのGerrit (コードレビューシステム) の利用方法に関する一般的な知識。
- GoプロジェクトのIssueトラッカーの歴史 (Google CodeからGitHubへの移行) に関する一般的な知識。