[インデックス 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
フラグなし)を実行しても、外部ネットワークテストは実行されませんでした。
この変更の背景には、おそらく以下の意図があったと考えられます。
- デフォルトのテストカバレッジの向上:
go test
を引数なしで実行する際に、外部ネットワークに依存する重要なテストがデフォルトで実行されないのは、テストカバレッジの観点から望ましくない場合があります。特に、ネットワーク関連のパッケージでは、実際のネットワーク接続を伴うテストが不可欠です。 - 開発者の利便性: 開発者がローカルで
go test
を実行する際に、外部ネットワークテストを明示的に有効にする手間を省き、より包括的なテストをデフォルトで実行できるようにすることで、開発ワークフローを簡素化します。 - テストの意図の明確化:
go test -short
は「短いテスト」を意味し、外部ネットワークテストをスキップする意図が明確です。一方で、go test
は「完全なテスト」を意味し、外部ネットワークテストを含むべきであるという設計思想への回帰、またはその強化が考えられます。
この変更により、go test
コマンドのデフォルトの挙動が、より包括的なテスト実行へとシフトし、外部ネットワークテストが通常のテストスイートの一部として扱われるようになります。
前提知識の解説
このコミットを理解するためには、Go言語のテストに関する以下の基本的な概念を理解しておく必要があります。
-
go test
コマンド: Go言語の標準的なテスト実行コマンドです。プロジェクトのルートディレクトリでgo test
を実行すると、カレントディレクトリとそのサブディレクトリにある_test.go
で終わるファイル内のテスト関数(TestXxx
という命名規則に従う関数)が実行されます。 -
testing
パッケージ: Go言語のテスト機能を提供する標準パッケージです。テスト関数は*testing.T
型の引数を受け取ります。この*testing.T
オブジェクトを通じて、テストの失敗を報告したり、テストをスキップしたり、ログを出力したりすることができます。 -
testing.Short()
関数:testing
パッケージが提供する関数で、go test -short
フラグが指定されている場合にtrue
を返します。この関数は、時間のかかるテストや外部リソースに依存するテストを条件付きでスキップするために使用されます。func TestSomethingLong(t *testing.T) { if testing.Short() { t.Skip("skipping test in short mode.") } // 時間のかかるテストロジック }
-
flag
パッケージ: Go言語のコマンドライン引数を解析するための標準パッケージです。プログラム内でカスタムのコマンドラインフラグを定義し、その値をプログラム内で利用することができます。flag.Bool(name string, value bool, usage string) *bool
: ブール型のフラグを定義します。name
はフラグ名(例: "external")、value
はデフォルト値、usage
はヘルプメッセージです。この関数は、フラグの値を保持する*bool
型のポインタを返します。flag.Parse()
: 定義されたすべてのフラグをコマンドライン引数から解析し、それぞれのフラグに対応する変数に値を設定します。テストでは、testing.Main
が自動的にflag.Parse()
を呼び出すため、通常は明示的に呼び出す必要はありません。
-
外部ネットワークテスト: ネットワーク接続を必要とするテストです。例えば、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")
この変更がもたらす影響は以下の通りです。
-
-external
フラグのデフォルト値:- 変更前は、
testExternal
フラグのデフォルト値はfalse
でした。これは、go test
コマンドを実行する際に、明示的に-external=true
を指定しない限り、*testExternal
の値はfalse
になることを意味します。 - 変更後は、
testExternal
フラグのデフォルト値がtrue
になりました。これにより、go test
コマンドを引数なしで実行した場合(つまり、-external
フラグを明示的に指定しない場合)、*testExternal
の値はデフォルトでtrue
になります。
- 変更前は、
-
テスト実行ロジックへの影響:
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
なし)を実行しても、*testExternal
がfalse
のままであれば、外部ネットワークテストは実行されませんでした。変更後:
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
だったため、!*testExternal
はtrue
となり、テストはスキップされていました。 - 変更後は、
*testExternal
のデフォルト値がtrue
になったため、!*testExternal
はfalse
となり、テストはスキップされなくなります。これにより、go test
を引数なしで実行した場合に、外部ネットワークテストが実行されるようになります。
- 変更前は、
-
テストのログメッセージの変更: スキップ時のログメッセージも「skipping external network test during -short」から「skipping test to avoid external network」に変更されています。これは、スキップの理由が単に
-short
フラグによるものではなく、-external
フラグの設定によっても発生しうることをより正確に反映しています。
この技術的な変更により、Goのnet
パッケージのテストは、デフォルトでより包括的なテストスイートを実行するようになり、開発者が明示的に-external=false
を指定しない限り、外部ネットワークへの接続を伴うテストも実行されるようになりました。これは、テストの網羅性を高め、潜在的なネットワーク関連のバグを早期に発見するのに役立ちます。
コアとなるコードの変更箇所
このコミットによるコードの変更は、主に以下の2つのファイルに集中しています。
src/pkg/net/dialgoogle_test.go
src/pkg/net/lookup_test.go
src/pkg/net/dialgoogle_test.go
の変更
このファイルでは、TestLookupCNAME
、TestDialGoogleIPv4
、TestDialGoogleIPv6
の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
なし)を実行しても、*testExternal
がfalse
のままであれば、これらの外部ネットワークテストは実質的に実行されませんでした。 -
変更後の条件
if testing.Short() || !*testExternal
: この条件は、論理OR (||
) を使用して2つの条件を結合しています。testing.Short()
:go test -short
が指定されている場合、この部分はtrue
となり、テストはスキップされます。これは以前の挙動と同じです。!*testExternal
:testExternal
フラグの値がfalse
の場合、この部分はtrue
となります。testExternal
のデフォルト値がtrue
になったため、go test
(-short
も-external
も指定しない場合)では*testExternal
はtrue
となり、!*testExternal
はfalse
になります。この結果、testing.Short() || !*testExternal
はfalse || false
となり、条件全体がfalse
になるため、テストはスキップされずに実行されます。- もしユーザーが明示的に
go test -external=false
と指定した場合、*testExternal
はfalse
となり、!*testExternal
はtrue
になります。この場合、testing.Short() || !*testExternal
はfalse || true
となり、条件全体がtrue
になるため、テストはスキップされます。
-
ログメッセージの変更: スキップ時に出力されるログメッセージも「skipping external network test during -short」から「skipping test to avoid external network」に変更されました。これは、テストがスキップされる理由が、単に
-short
フラグによるものだけでなく、-external
フラグの設定によっても発生しうることをより正確に示しています。
これらの変更により、go test
コマンドのデフォルトの挙動が、外部ネットワークテストを含むように調整され、テストの網羅性と開発者の利便性が向上しました。
関連リンク
- https://golang.org/cl/5696079 (Gerrit Change-Id)
参考にした情報源リンク
- Go言語の
testing
パッケージに関する公式ドキュメント: https://pkg.go.dev/testing - Go言語の
flag
パッケージに関する公式ドキュメント: https://pkg.go.dev/flag go test
コマンドに関する公式ドキュメント: https://pkg.go.dev/cmd/go#hdr-Test_packagesgo help testflag
(コマンドラインでgo help testflag
を実行すると、テストフラグに関する詳細な情報が表示されます)- Go言語のテストに関する一般的な情報源 (例: Go by Example - Testing): https://gobyexample.com/testing
- Go言語のテストにおける
testing.Short()
の利用例: https://stackoverflow.com/questions/11823007/what-does-testing-short-do-in-go - Go言語の
flag
パッケージの利用例: https://gobyexample.com/command-line-flags