Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 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/tourgo.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のコード例を自動的にテストするための新しいメカニズムの導入です。

  1. 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 foofoo が出力に含まれることを確認しています。
    • 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 関数は、テストが失敗した場合に統一されたエラーメッセージを出力し、スクリプトを終了させるためのヘルパー関数です。
  2. src/run.bash の変更:

    • src/run.bash は、Goプロジェクト全体のテストスイートやビルドプロセスの一部として実行されるメインのシェルスクリプトです。
    • 以前は、doc/codewalk ディレクトリ内の pig.gourlpoll.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/nullgrep の出力を破棄し、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のコード例の自動テストが統合され、ドキュメントのコード例が常に最新かつ動作可能であることが保証されるようになりました。

関連リンク

参考にした情報源リンク

  • 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への移行) に関する一般的な知識。