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

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

このコミットは、Go言語の標準ライブラリnetパッケージにおけるテストの挙動を変更するものです。具体的には、外部ネットワークへの接続を伴うテスト("external"テスト)を制御するための-externalフラグのデフォルト値をfalseからtrueに変更し、go testコマンドの実行時に外部ネットワークテストがデフォルトで実行されるように調整しています。これにより、go test単体で実行される「長いテスト」の際に、外部ネットワークへの接続を伴うテストが自動的に含まれるようになります。

コミット

commit 7301065fcc8afbf4f5feb38c0460c0796642f4aa
Author: Mikio Hara <mikioh.mikioh@gmail.com>
Date:   Thu Mar 1 07:39:03 2012 +0900

    net: make -external flag for tests default to true
    
    go test -short # like in the build; no external stuff
    go test # long tests, + external
    go test -external=false # long tests, no external
    
    R=golang-dev, rsc
    CC=golang-dev
    https://golang.org/cl/5696079

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

https://github.com/golang/go/commit/7301065fcc8afbf4f5feb38c0460c0796642f4aa

元コミット内容

このコミットは、netパッケージのテストにおいて、-externalというテストフラグのデフォルト値をtrueに変更することを目的としています。

コミットメッセージには、この変更がgo testコマンドの異なる実行シナリオにどのように影響するかを簡潔に説明しています。

  • go test -short: ビルドシステムでの実行時と同様に、外部ネットワークに依存するテストは実行されません。
  • go test: デフォルトで実行される「長いテスト」の際に、外部ネットワークに依存するテストも含まれるようになります。
  • go test -external=false: 「長いテスト」の際でも、明示的に外部ネットワークに依存するテストを除外することができます。

これは、テストの実行環境や目的に応じて、外部ネットワークへの依存を柔軟に制御できるようにするための改善です。

変更の背景

Go言語のテストフレームワークには、テストの実行時間を制御するためのメカニズムがいくつか存在します。その一つがtesting.Short()関数と、それに連携するgo test -shortフラグです。

  • go test -short: このフラグが指定されると、testing.Short()関数はtrueを返します。開発者はこのtesting.Short()の戻り値を利用して、時間のかかるテストや外部リソースに依存するテストをスキップするロジックをテストコード内に記述することが一般的です。これにより、CI/CD環境での高速なテスト実行や、開発中の迅速なフィードバックが可能になります。

このコミット以前は、netパッケージの外部ネットワークに依存するテストは、testing.Short()trueの場合にスキップされるだけでなく、-externalフラグが明示的にtrueに設定されていない限り、デフォルトでは実行されないようになっていました。つまり、go test-shortフラグなし)を実行しても、外部ネットワークテストは実行されませんでした。

この変更の背景には、おそらく以下の意図があったと考えられます。

  1. デフォルトのテストカバレッジの向上: go testを引数なしで実行する際に、外部ネットワークに依存する重要なテストがデフォルトで実行されないのは、テストカバレッジの観点から望ましくない場合があります。特に、ネットワーク関連のパッケージでは、実際のネットワーク接続を伴うテストが不可欠です。
  2. 開発者の利便性: 開発者がローカルでgo testを実行する際に、外部ネットワークテストを明示的に有効にする手間を省き、より包括的なテストをデフォルトで実行できるようにすることで、開発ワークフローを簡素化します。
  3. テストの意図の明確化: go test -shortは「短いテスト」を意味し、外部ネットワークテストをスキップする意図が明確です。一方で、go testは「完全なテスト」を意味し、外部ネットワークテストを含むべきであるという設計思想への回帰、またはその強化が考えられます。

この変更により、go testコマンドのデフォルトの挙動が、より包括的なテスト実行へとシフトし、外部ネットワークテストが通常のテストスイートの一部として扱われるようになります。

前提知識の解説

このコミットを理解するためには、Go言語のテストに関する以下の基本的な概念を理解しておく必要があります。

  1. go testコマンド: Go言語の標準的なテスト実行コマンドです。プロジェクトのルートディレクトリでgo testを実行すると、カレントディレクトリとそのサブディレクトリにある_test.goで終わるファイル内のテスト関数(TestXxxという命名規則に従う関数)が実行されます。

  2. testingパッケージ: Go言語のテスト機能を提供する標準パッケージです。テスト関数は*testing.T型の引数を受け取ります。この*testing.Tオブジェクトを通じて、テストの失敗を報告したり、テストをスキップしたり、ログを出力したりすることができます。

  3. testing.Short()関数: testingパッケージが提供する関数で、go test -shortフラグが指定されている場合にtrueを返します。この関数は、時間のかかるテストや外部リソースに依存するテストを条件付きでスキップするために使用されます。

    func TestSomethingLong(t *testing.T) {
        if testing.Short() {
            t.Skip("skipping test in short mode.")
        }
        // 時間のかかるテストロジック
    }
    
  4. flagパッケージ: Go言語のコマンドライン引数を解析するための標準パッケージです。プログラム内でカスタムのコマンドラインフラグを定義し、その値をプログラム内で利用することができます。

    • flag.Bool(name string, value bool, usage string) *bool: ブール型のフラグを定義します。nameはフラグ名(例: "external")、valueはデフォルト値、usageはヘルプメッセージです。この関数は、フラグの値を保持する*bool型のポインタを返します。
    • flag.Parse(): 定義されたすべてのフラグをコマンドライン引数から解析し、それぞれのフラグに対応する変数に値を設定します。テストでは、testing.Mainが自動的にflag.Parse()を呼び出すため、通常は明示的に呼び出す必要はありません。
  5. 外部ネットワークテスト: ネットワーク接続を必要とするテストです。例えば、DNSルックアップ、HTTPリクエスト、TCP/UDP接続など、実際のインターネット上のサービスやローカルネットワーク上のサービスと通信するテストを指します。これらのテストは、ネットワークの状態や外部サービスの可用性に依存するため、不安定になる可能性があり、また実行に時間がかかることがあります。

これらの概念を理解することで、コミットがgo testの挙動とテストの制御にどのように影響を与えるかが明確になります。

技術的詳細

このコミットの技術的な核心は、src/pkg/net/lookup_test.goファイル内で定義されているtestExternalというブール型フラグのデフォルト値の変更にあります。

変更前:

var testExternal = flag.Bool("external", false, "allow use of external networks during test")

変更後:

var testExternal = flag.Bool("external", true, "allow use of external networks during long test")

この変更がもたらす影響は以下の通りです。

  1. -externalフラグのデフォルト値:

    • 変更前は、testExternalフラグのデフォルト値はfalseでした。これは、go testコマンドを実行する際に、明示的に-external=trueを指定しない限り、*testExternalの値はfalseになることを意味します。
    • 変更後は、testExternalフラグのデフォルト値がtrueになりました。これにより、go testコマンドを引数なしで実行した場合(つまり、-externalフラグを明示的に指定しない場合)、*testExternalの値はデフォルトでtrueになります。
  2. テスト実行ロジックへの影響: src/pkg/net/dialgoogle_test.goおよびsrc/pkg/net/lookup_test.go内の複数のテスト関数では、外部ネットワークへの接続を伴う処理の前に、以下の条件チェックを行っていました。

    変更前:

    if testing.Short() {
        // Don't use external network.
        t.Logf("skipping external network test during -short")
        return
    }
    

    このロジックは、go test -shortが指定された場合にのみテストをスキップしていました。しかし、-externalフラグのデフォルト値がfalseであったため、go test-shortなし)を実行しても、*testExternalfalseのままであれば、外部ネットワークテストは実行されませんでした。

    変更後:

    if testing.Short() || !*testExternal {
        t.Logf("skipping test to avoid external network")
        return
    }
    

    この変更により、テストのスキップ条件に!*testExternalが追加されました。

    • testing.Short()trueの場合(go test -short実行時)は、引き続きテストがスキップされます。これは、短いテスト実行の意図に合致します。
    • testing.Short()falseの場合(go test実行時)は、!*testExternalの評価が重要になります。
      • 変更前は、*testExternalのデフォルト値がfalseだったため、!*testExternaltrueとなり、テストはスキップされていました。
      • 変更後は、*testExternalのデフォルト値がtrueになったため、!*testExternalfalseとなり、テストはスキップされなくなります。これにより、go testを引数なしで実行した場合に、外部ネットワークテストが実行されるようになります。
  3. テストのログメッセージの変更: スキップ時のログメッセージも「skipping external network test during -short」から「skipping test to avoid external network」に変更されています。これは、スキップの理由が単に-shortフラグによるものではなく、-externalフラグの設定によっても発生しうることをより正確に反映しています。

この技術的な変更により、Goのnetパッケージのテストは、デフォルトでより包括的なテストスイートを実行するようになり、開発者が明示的に-external=falseを指定しない限り、外部ネットワークへの接続を伴うテストも実行されるようになりました。これは、テストの網羅性を高め、潜在的なネットワーク関連のバグを早期に発見するのに役立ちます。

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

このコミットによるコードの変更は、主に以下の2つのファイルに集中しています。

  1. src/pkg/net/dialgoogle_test.go
  2. src/pkg/net/lookup_test.go

src/pkg/net/dialgoogle_test.go の変更

このファイルでは、TestLookupCNAMETestDialGoogleIPv4TestDialGoogleIPv6の3つのテスト関数において、テストスキップの条件が変更されています。

--- a/src/pkg/net/dialgoogle_test.go
+++ b/src/pkg/net/dialgoogle_test.go
@@ -42,9 +42,8 @@ func doDial(t *testing.T, network, addr string) {
 }
 
 func TestLookupCNAME(t *testing.T) {
-	if testing.Short() {
-		// Don't use external network.
-		t.Logf("skipping external network test during -short")
+	if testing.Short() || !*testExternal {
+		t.Logf("skipping test to avoid external network")
 		return
 	}
 	cname, err := LookupCNAME("www.google.com")
@@ -67,9 +66,8 @@ var googleaddrsipv4 = []string{
 }
 
 func TestDialGoogleIPv4(t *testing.T) {
-	if testing.Short() {
-		// Don't use external network.
-		t.Logf("skipping external network test during -short")
+	if testing.Short() || !*testExternal {
+		t.Logf("skipping test to avoid external network")
 		return
 	}
 
@@ -124,9 +122,8 @@ var googleaddrsipv6 = []string{
 }
 
 func TestDialGoogleIPv6(t *testing.T) {
-	if testing.Short() {
-		// Don't use external network.
-		t.Logf("skipping external network test during -short")
+	if testing.Short() || !*testExternal {
+		t.Logf("skipping test to avoid external network")
 		return
 	}
 	// Only run tcp6 if the kernel will take it.

src/pkg/net/lookup_test.go の変更

このファイルでは、testExternalフラグの定義が変更されています。

--- a/src/pkg/net/lookup_test.go
+++ b/src/pkg/net/lookup_test.go
@@ -12,7 +12,7 @@ import (
 	"testing"
 )
 
-var testExternal = flag.Bool("external", false, "allow use of external networks during test")
+var testExternal = flag.Bool("external", true, "allow use of external networks during long test")
 
 func TestGoogleSRV(t *testing.T) {
  	if testing.Short() || !*testExternal {

コアとなるコードの解説

src/pkg/net/lookup_test.go の変更点

-var testExternal = flag.Bool("external", false, "allow use of external networks during test")
+var testExternal = flag.Bool("external", true, "allow use of external networks during long test")

この行は、testExternalという名前のコマンドラインフラグを定義しています。

  • flag.Boolは、ブール型のフラグを定義するための関数です。
  • 第一引数 "external" は、このフラグの名前です。コマンドラインで-externalとして指定されます。
  • 第二引数は、このフラグのデフォルト値です。
    • 変更前はfalseでした。これは、go testコマンドを実行する際に-externalフラグを明示的に指定しない場合、testExternalの値はfalseになることを意味します。
    • 変更後はtrueになりました。これにより、go testコマンドを引数なしで実行した場合、testExternalの値はデフォルトでtrueになります。
  • 第三引数は、このフラグの用途を説明するヘルプメッセージです。メッセージも「allow use of external networks during test」から「allow use of external networks during long test」に変更され、デフォルトで外部ネットワークテストが「長いテスト」の一部として実行されるという意図がより明確になっています。

この変更が、外部ネットワークテストのデフォルトの実行挙動を決定する最も重要な部分です。

src/pkg/net/dialgoogle_test.go および src/pkg/net/lookup_test.go のテストスキップ条件の変更点

以下のコードブロックは、dialgoogle_test.go内の3つのテスト関数(TestLookupCNAME, TestDialGoogleIPv4, TestDialGoogleIPv6)と、lookup_test.go内のTestGoogleSRV関数に共通して適用された変更です。

-	if testing.Short() {
-		// Don't use external network.
-		t.Logf("skipping external network test during -short")
+	if testing.Short() || !*testExternal {
+		t.Logf("skipping test to avoid external network")
 		return
 	}
  • 変更前の条件 if testing.Short(): この条件は、go test -shortフラグが指定された場合にのみtrueとなり、テストがスキップされていました。しかし、前述の通り、-externalフラグのデフォルト値がfalseであったため、go test-shortなし)を実行しても、*testExternalfalseのままであれば、これらの外部ネットワークテストは実質的に実行されませんでした。

  • 変更後の条件 if testing.Short() || !*testExternal: この条件は、論理OR (||) を使用して2つの条件を結合しています。

    1. testing.Short(): go test -shortが指定されている場合、この部分はtrueとなり、テストはスキップされます。これは以前の挙動と同じです。
    2. !*testExternal: testExternalフラグの値がfalseの場合、この部分はtrueとなります。
      • testExternalのデフォルト値がtrueになったため、go test-short-externalも指定しない場合)では*testExternaltrueとなり、!*testExternalfalseになります。この結果、testing.Short() || !*testExternalfalse || falseとなり、条件全体がfalseになるため、テストはスキップされずに実行されます。
      • もしユーザーが明示的にgo test -external=falseと指定した場合、*testExternalfalseとなり、!*testExternaltrueになります。この場合、testing.Short() || !*testExternalfalse || trueとなり、条件全体がtrueになるため、テストはスキップされます。
  • ログメッセージの変更: スキップ時に出力されるログメッセージも「skipping external network test during -short」から「skipping test to avoid external network」に変更されました。これは、テストがスキップされる理由が、単に-shortフラグによるものだけでなく、-externalフラグの設定によっても発生しうることをより正確に示しています。

これらの変更により、go testコマンドのデフォルトの挙動が、外部ネットワークテストを含むように調整され、テストの網羅性と開発者の利便性が向上しました。

関連リンク

参考にした情報源リンク