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

[インデックス 11938] ファイルの概要

このコミットは、Go言語のコマンドラインツール gotest サブコマンドにおけるユーザーエクスペリエンスの改善を目的としています。具体的には、go test 実行時にパッケージのインストールが必要な場合に、将来のテスト実行を高速化するための go test -i コマンドの提案メッセージをより正確にする変更です。

コミット

commit 53d94a7220aa2ff67f29621dc6fd7d450e945229
Author: Shenghou Ma <minux.ma@gmail.com>
Date:   Wed Feb 15 13:26:50 2012 -0500

    cmd/go: suggest 'go test -i [args to test]'
            Fixes #3023.
    
    R=rsc
    CC=golang-dev
    https://golang.org/cl/5674055

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/53d94a7220aa2ff67f29621dc6fd7d450e945229

元コミット内容

cmd/go: go test -i [args to test] を提案する Fixes #3023.

R=rsc CC=golang-dev https://golang.org/cl/5674055

変更の背景

Go言語の go test コマンドは、テストを実行する前に必要なパッケージを自動的にビルド・インストールします。しかし、このビルド・インストールプロセスは、特に多数の依存関係を持つプロジェクトや、頻繁にテストを実行する開発者にとっては、時間のロスとなる可能性があります。

go test -i コマンドは、テスト対象のパッケージとその依存関係を事前にインストールすることで、その後のテスト実行を高速化する機能を提供します。しかし、以前の実装では、go test がパッケージのインストールを促すメッセージを表示する際に、単に go test -i とだけ表示し、テスト対象のパッケージ引数を省略していました。

これにより、ユーザーはどのパッケージに対して -i フラグを適用すべきか不明瞭であり、手動でパッケージ名を追記する必要がありました。このコミットは、この提案メッセージを改善し、ユーザーがコピー&ペーストでそのまま実行できるような、より具体的なコマンドを提示することを目的としています。コミットメッセージにある Fixes #3023 は、この問題がGoの内部課題追跡システムで認識されていたことを示しています。

前提知識の解説

  • go test コマンド: Go言語の標準的なテスト実行コマンドです。指定されたパッケージ内のテストファイル(_test.go で終わるファイル)を見つけ、テスト関数を実行します。テスト実行前に、テスト対象のパッケージとその依存関係をビルド・インストールします。
  • go install コマンド: Go言語のパッケージをビルドし、GOPATH/bin または GOBIN で指定されたディレクトリに実行可能ファイルをインストールするコマンドです。go test -i は内部的にこの go install のような動作を行い、テストに必要なパッケージのビルド済みバイナリをキャッシュすることで、その後のテスト実行を高速化します。
  • -i フラグ: go test コマンドに渡されるフラグの一つで、テスト対象のパッケージとその依存関係を事前にインストール(ビルドしてキャッシュ)します。これにより、次回以降のテスト実行時にビルドプロセスをスキップできるため、テストの起動時間が短縮されます。
  • 標準エラー出力 (os.Stderr): プログラムがエラーメッセージや診断情報を出力するために使用するストリームです。このコミットでは、ユーザーへの提案メッセージが標準エラー出力に表示されます。

技術的詳細

この変更は、src/cmd/go/test.go ファイル内の runTest 関数にあります。この関数は go test コマンドの主要なロジックを処理します。

変更前のコードでは、warned フラグが true の場合(つまり、パッケージのインストールが必要で、ユーザーに go test -i の使用を促す必要がある場合)、以下のメッセージが標準エラー出力に表示されていました。

fmt.Fprintf(os.Stderr, "installing these packages with 'go test -i' will speed future tests.\\n\\n")

このメッセージは、どのパッケージに対して -i フラグを適用すべきかを示していませんでした。

変更後のコードでは、このメッセージが動的に生成されるように修正されました。具体的には、テスト対象のパッケージ引数 (pkgArgs) を取得し、それを go test -i コマンドに含めるようにしています。

  1. pkgArgs スライス(テスト対象のパッケージ名が格納されている)を strings.Join(pkgArgs, " ") を使ってスペース区切りの文字列に結合します。
  2. 結合された文字列が空でない場合(つまり、特定のパッケージが指定されている場合)、その文字列の前にスペースを追加します。これは、go test -i の後に引数を適切に配置するためです。
  3. 最終的なメッセージは、fmt.Fprintf を使用して、go test -i の後に動的に生成されたパッケージ引数を挿入する形式に変更されました。
args := strings.Join(pkgArgs, " ")
if args != "" {
    args = " " + args
}
fmt.Fprintf(os.Stderr, "installing these packages with 'go test -i%s' will speed future tests.\\n\\n", args)

この変更により、例えば go test ./... のように実行した場合に、go test -i ./... のように具体的なコマンドが提案されるようになり、ユーザーの利便性が向上しました。

コアとなるコードの変更箇所

--- a/src/cmd/go/test.go
+++ b/src/cmd/go/test.go
@@ -357,7 +357,11 @@ func runTest(cmd *Command, args []string) {
 		}
 	}
 	if warned {
-		fmt.Fprintf(os.Stderr, "installing these packages with 'go test -i' will speed future tests.\\n\\n")
+		args := strings.Join(pkgArgs, " ")
+		if args != "" {
+			args = " " + args
+		}
+		fmt.Fprintf(os.Stderr, "installing these packages with 'go test -i%s' will speed future tests.\\n\\n", args)
 	}
 
 	b.do(root)

コアとなるコードの解説

変更は src/cmd/go/test.go ファイルの runTest 関数内、warned 変数が true の場合の条件分岐にあります。

  • args := strings.Join(pkgArgs, " "): pkgArgs は、go test コマンドに渡されたパッケージ引数のリストです。例えば、go test mypackage ./... のように実行された場合、pkgArgs には ["mypackage", "./..."] のような値が含まれます。この行では、それらの引数をスペースで結合し、args という新しい文字列変数に代入しています。結果として、"mypackage ./..." のような文字列が生成されます。

  • if args != "" { args = " " + args }: もし args が空でない場合(つまり、go test にパッケージ引数が渡された場合)、args の先頭にスペースを追加しています。これは、fmt.Fprintf で最終的なメッセージを整形する際に、go test -i の後に適切なスペースを挿入するためです。例えば、go test -imypackage の間にスペースが必要になります。

  • fmt.Fprintf(os.Stderr, "installing these packages with 'go test -i%s' will speed future tests.\\n\\n", args): この行が、ユーザーに表示されるメッセージを生成しています。

    • os.Stderr: 標準エラー出力にメッセージを出力することを指定しています。
    • "installing these packages with 'go test -i%s' will speed future tests.\\n\\n": フォーマット文字列です。%s の部分に、先ほど生成した args 変数の内容が挿入されます。
    • args: go test に渡されたパッケージ引数(先頭にスペースが付加されている可能性あり)がここに挿入されます。

この変更により、例えば go test mypackage と実行して、そのパッケージがインストールされていない場合に、以下のようなメッセージが表示されるようになります。

installing these packages with 'go test -i mypackage' will speed future tests.

これにより、ユーザーは提案されたコマンドをそのままコピー&ペーストして実行できるようになり、利便性が大幅に向上します。

関連リンク

参考にした情報源リンク