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

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

このコミットは、Go言語の初期のテストフレームワークにおいて、テストの実行状況をより詳細に出力するための -chatty フラグを追加するものです。具体的には、src/lib/testing.go ファイルに変更が加えられ、テストの開始時 (=== RUN) と成功時 (--- PASS) にメッセージを出力する機能が導入されました。これにより、ユーザーはテストの進行状況をより詳細に把握できるようになります。

コミット

commit 23bd1298f746102b33263617ea3c90239239ab4a
Author: Russ Cox <rsc@golang.org>
Date:   Tue Nov 18 17:52:05 2008 -0800

    add -chatty flag to test.
    was supposed to be in some other cl but got dropped.
    
    R=r
    DELTA=21  (16 added, 2 deleted, 3 changed)
    OCL=19531
    CL=19539

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

https://github.com/golang/go/commit/23bd1298f746102b33263617ea3c90239239ab4a

元コミット内容

add -chatty flag to test.
was supposed to be in some other cl but got dropped.

R=r
DELTA=21  (16 added, 2 deleted, 3 changed)
OCL=19531
CL=19539

変更の背景

このコミットの背景には、Go言語のテスト実行時の出力に関する改善の意図があります。コミットメッセージにある「was supposed to be in some other cl but got dropped.」という記述から、この -chatty フラグの追加は元々別の変更リスト(Change List, CL)に含まれる予定だったが、何らかの理由でそのCLからは除外され、改めて独立したコミットとして追加されたことが伺えます。

テストの実行において、通常は失敗したテストのみが報告され、成功したテストについては簡潔なサマリーのみが表示されることが多いです。しかし、大規模なテストスイートや、特定のテストの実行状況を詳細に追跡したい場合、成功したテストも含めて個々のテストの開始と終了、そしてその結果を逐次的に表示する機能が求められることがあります。この -chatty フラグは、そのような詳細な出力("chatty" = おしゃべりな、多弁な)を有効にするために導入されました。これにより、開発者はテストの進行状況をより細かく把握し、デバッグや問題の特定を容易にすることができます。

前提知識の解説

このコミットを理解するためには、以下のGo言語の基本的な概念と、当時のテストフレームワークの構造に関する知識が必要です。

  1. Go言語の flag パッケージ: Go言語には、コマンドライン引数を解析するための標準パッケージ flag があります。このパッケージを使用すると、プログラムの実行時に -name value の形式で引数を渡すことで、プログラムの挙動を動的に変更できます。

    • flag.Bool(name, default_value, *variable, usage): ブール型のフラグを定義し、その値を指定された変数にバインドします。
    • flag.Parse(): コマンドライン引数を実際に解析し、定義されたフラグに対応する変数に値を設定します。この関数は通常、main 関数の冒頭で呼び出されます。
  2. Go言語の init 関数: Go言語には、パッケージがインポートされた際に自動的に実行される init 関数という特別な関数があります。各パッケージは複数の init 関数を持つことができ、これらはパッケージ内のすべての変数の宣言と初期化が完了した後、かつ main 関数が実行される前に、宣言された順序で実行されます。このコミットでは、init 関数内で -chatty フラグを定義しています。

  3. Go言語の初期のテストフレームワーク (testing パッケージ): Go言語のテストは、testing パッケージを使用して記述されます。当時のGoのテストフレームワークは現在とは異なる部分が多く、このコミットに見られるように、Test 構造体や Main 関数といった要素が直接公開されていました。

    • export type Test struct { name string; f *() bool; }: テストの構造を定義しています。name はテスト名、f はテスト関数へのポインタ(当時のGoの関数型は現在と表記が異なる場合があります)です。
    • export func Main(tests *[]Test): テストスイートのエントリポイントとなる関数です。この関数が、与えられたテストのリストを順に実行します。
  4. println 関数と sys.exit: 当時のGo言語では、標準出力への出力には println 関数が使われていました。また、プログラムの終了コードを設定するには sys.exit が使われていました。これらは現在の fmt パッケージや os.Exit に相当する機能です。

技術的詳細

このコミットの技術的な核心は、Go言語の flag パッケージと testing パッケージの連携にあります。

  1. フラグの定義と初期化: src/lib/testing.go の冒頭に import ("flag") が追加され、flag パッケージが利用可能になります。 var chatty bool; でブール型の変数 chatty が宣言されます。この変数が -chatty フラグの値を保持します。 func init() { flag.Bool("chatty", false, &chatty, "chatty"); } という init 関数が追加されます。この関数は、testing パッケージがロードされる際に自動的に実行され、以下の処理を行います。

    • flag.Bool("chatty", false, &chatty, "chatty"): -chatty という名前のブール型フラグを定義します。デフォルト値は false で、その値は chatty 変数に格納されます。最後の "chatty" はフラグの利用方法を示す説明文です。
  2. コマンドライン引数の解析: export func Main(tests *[]Test) 関数の冒頭に flag.Parse(); が追加されます。これにより、テストが実行される前にコマンドライン引数が解析され、もし -chatty フラグが指定されていれば、chatty 変数の値が true に設定されます。

  3. テスト出力の制御: テストのループ内で、chatty 変数の値に基づいて出力が制御されます。

    • if chatty { println("=== RUN ", tests[i].name); }: テストが実行される直前に、chattytrue の場合にのみ「=== RUN [テスト名]」というメッセージが出力されます。これにより、どのテストが現在実行されているかが明確になります。
    • if !ok1 { ok = false; println("--- FAIL", tests[i].name); }: テストが失敗した場合 (ok1false) は、chatty の値に関わらず「--- FAIL [テスト名]」というメッセージが出力されます。これは、失敗したテストは常に報告されるべきであるという原則に基づいています。
    • else if chatty { println("--- PASS", tests[i].name); }: テストが成功した場合 (ok1true) かつ chattytrue の場合にのみ、「--- PASS [テスト名]」というメッセージが出力されます。chattyfalse の場合、成功したテストに関する個別の出力は行われません。

この変更により、ユーザーは -chatty フラグを付けてテストを実行することで、より詳細なテストの実行ログを得られるようになります。

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

src/lib/testing.go ファイルにおける変更は以下の通りです。

--- a/src/lib/testing.go
+++ b/src/lib/testing.go
@@ -4,23 +4,37 @@
 
  package testing
  
+ import (
+ 	"flag"
+ )
+ 
+ var chatty bool;
+ func init() {
+ 	flag.Bool("chatty", false, &chatty, "chatty");
+ }
+ 
  export type Test struct {
  	name string;
  	f *() bool;
  }
  
  export func Main(tests *[]Test) {
+\tflag.Parse();
  	ok := true;
  	for i := 0; i < len(tests); i++ {\
+\t\tif chatty {\
+\t\t\tprintln("=== RUN ", tests[i].name);\
+\t\t}\
  		ok1 := tests[i].f();
-\t\tstatus := "FAIL";
-\t\tif ok1 {\
-\t\t\tstatus = "PASS"
+\t\tif !ok1 {\
+\t\t\tok = false;\
+\t\t\tprintln("--- FAIL", tests[i].name);\
+\t\t} else if chatty {\
+\t\t\tprintln("--- PASS", tests[i].name);\
  		}\
-\t\tok = ok && ok1;\
-\t\tprintln(status, tests[i].name);\
  	}\
  	if !ok {\
  		sys.exit(1);\
  	}\
+\tprintln("PASS");
  }

コアとなるコードの解説

  1. import ("flag") の追加: Goの標準ライブラリである flag パッケージをインポートしています。これにより、コマンドライン引数を扱う機能が利用可能になります。

  2. var chatty bool; の宣言: chatty という名前のブール型変数を宣言しています。この変数は、-chatty コマンドラインフラグが指定されたかどうかを保持します。デフォルトではGoのブール型変数は false に初期化されます。

  3. func init() { flag.Bool("chatty", false, &chatty, "chatty"); } の追加: init 関数は、パッケージがロードされる際に自動的に実行される特別な関数です。この中で flag.Bool を呼び出すことで、-chatty という名前のコマンドラインフラグを定義しています。

    • 最初の "chatty" はフラグの名前です。
    • false はこのフラグのデフォルト値です。
    • &chatty は、フラグの値が解析されたときにその値を格納する変数のアドレスです。
    • 最後の "chatty" は、フラグの簡単な説明文です(ヘルプメッセージなどで表示されます)。
  4. flag.Parse(); の追加: export func Main(tests *[]Test) 関数の冒頭に flag.Parse() が追加されました。この関数は、プログラムに渡されたコマンドライン引数を解析し、定義されたフラグ(この場合は -chatty)の値を対応する変数(chatty)に設定します。これにより、テスト実行時にユーザーが指定したフラグがプログラムに反映されます。

  5. テスト結果出力ロジックの変更: テストのループ内で、テストの実行状況と結果の出力方法が変更されています。

    • テスト開始時の出力: if chatty { println("=== RUN ", tests[i].name); } chatty フラグが true の場合のみ、現在実行中のテストの名前の前に「=== RUN 」というプレフィックスを付けて出力します。これにより、テストが開始されたことを明示的に示します。
    • テスト失敗時の出力: if !ok1 { ok = false; println("--- FAIL", tests[i].name); } テストが失敗した場合 (ok1false) は、chatty フラグの状態に関わらず、常に「--- FAIL [テスト名]」というメッセージを出力します。これは、テストの失敗は常にユーザーに通知されるべき重要な情報であるためです。
    • テスト成功時の出力: else if chatty { println("--- PASS", tests[i].name); } テストが成功した場合 (ok1true) かつ chatty フラグが true の場合にのみ、「--- PASS [テスト名]」というメッセージを出力します。chattyfalse の場合、成功したテストに関する個別の出力は抑制され、より簡潔な出力になります。
    • 元の出力の削除: status := "FAIL"; if ok1 { status = "PASS" } ok = ok && ok1; println(status, tests[i].name); 上記の元の出力ロジックが削除され、新しい条件付き出力に置き換えられました。
  6. 最終的な「PASS」出力の追加: println("PASS"); すべてのテストが成功した場合に、最後に「PASS」というメッセージが出力されるようになりました。これは、テストスイート全体の成功を示すものです。

これらの変更により、Goのテストフレームワークは、ユーザーが -chatty フラグを通じてテスト出力の詳細度を制御できるようになり、より柔軟なテスト実行環境を提供できるようになりました。

関連リンク

参考にした情報源リンク