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

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

このコミットは、Go言語のテストフレームワークにおける-test.timeoutフラグの挙動を変更し、時間指定の柔軟性と明確性を向上させるものです。具体的には、タイムアウト値を秒単位の整数(int64)で受け取る形式から、time.Duration型で表現される期間(例: "10s", "2m")で受け取る形式へと変更しています。これにより、ユーザーはより直感的で読みやすい形式でテストのタイムアウトを設定できるようになります。

コミット

commit 57c9bb4a07b0ac483935e321ef760c0c52f8efd4
Author: David Symonds <dsymonds@golang.org>
Date:   Sun Dec 25 16:07:05 2011 +1100

    testing: use flag.Duration for -timeout flag.
    
    R=golang-dev, gustavo, r
    CC=golang-dev
    https://golang.org/cl/5498077

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

https://github.com/golang/go/commit/57c9bb4a07b0ac483935e321ef760c0c52f8efd4

元コミット内容

testing: use flag.Duration for -timeout flag.

R=golang-dev, gustavo, r
CC=golang-dev
https://golang.org/cl/5498077

変更の背景

Go言語のテストフレームワークには、テストが無限に実行されるのを防ぐためのタイムアウト機能が備わっています。以前は、このタイムアウトは-test.timeout Nのように、Nに秒数を指定する形式でした。しかし、この形式では、例えば「2分」や「300ミリ秒」といった、より人間が理解しやすい時間単位での指定ができませんでした。また、内部的にはint64型で秒数を管理していたため、time.Duration型が提供する時間単位の表現力を活用できていませんでした。

このコミットの背景には、ユーザーエクスペリエンスの向上と、Go言語の標準ライブラリであるtimeパッケージのDuration型との整合性を高める目的があります。time.Durationは、時間量を表現するための型であり、"ns", "us", "ms", "s", "m", "h"といった単位をサポートしています。これにより、ユーザーはより直感的で柔軟なタイムアウト指定が可能になります。

前提知識の解説

Go言語のflagパッケージ

Go言語のflagパッケージは、コマンドライン引数を解析するための標準ライブラリです。プログラムの起動時にユーザーが指定するオプション(フラグ)を定義し、その値をプログラム内で利用できるようにします。例えば、-timeoutのようなフラグを定義し、その値を取得するためにflag.Int64flag.Stringなどの関数を使用します。このコミットでは、新たにflag.Durationという関数が利用されています。

Go言語のtimeパッケージとtime.Duration

Go言語のtimeパッケージは、時間と日付を扱うための機能を提供します。その中でもtime.Duration型は、時間の長さを表現するための型です。これはナノ秒単位の整数として内部的に表現されますが、time.ParseDuration関数やtime.Duration型のメソッド(例: String())を使うことで、"10s"(10秒)や"2m"(2分)のような人間が読みやすい文字列形式と相互変換できます。これにより、時間に関する処理をより安全かつ直感的に記述できるようになります。

Go言語のテストフレームワーク

Go言語には、go testコマンドを通じて実行される組み込みのテストフレームワークがあります。開発者は_test.goというサフィックスを持つファイルにテストコードを記述し、testingパッケージの機能を利用してユニットテスト、ベンチマークテスト、サンプルコードなどを実行します。-test.timeoutフラグは、このテスト実行全体または個々のテストの実行時間に上限を設けるために使用されます。

技術的詳細

このコミットの主要な変更点は、-test.timeoutフラグの型をint64からtime.Durationに変更したことです。

  1. flag.Int64からflag.Durationへの変更:

    • src/pkg/testing/testing.goにおいて、timeout変数の定義がflag.Int64("test.timeout", 0, ...)からflag.Duration("test.timeout", 0, ...)に変更されました。
    • flag.Durationは、コマンドラインから"10s"や"2m"のような文字列を受け取り、それをtime.Duration型にパースして変数に格納します。これにより、ユーザーはより自然な時間単位でタイムアウトを指定できるようになります。
  2. time.Duration型の直接利用:

    • 以前は、*timeoutint64型)に秒数が格納されており、time.Duration(*timeout)*time.Secondのようにtime.Secondを掛けてtime.Duration型に変換していました。
    • 変更後は、*timeout自体がtime.Duration型であるため、time.AfterFunc(*timeout, alarm)のように直接time.AfterFuncに渡すことができるようになりました。これにより、コードがより簡潔になり、型変換の誤りを防ぐことができます。
  3. ドキュメントと使用例の更新:

    • src/cmd/go/test.gosrc/cmd/gotest/doc.goのドキュメントが更新され、-test.timeoutフラグの引数が「n秒」から「t(期間)」へと変更されました。
    • src/Make.pkgでは、testshortターゲットの-test.timeoutの値が120(秒)から2m(2分)に変更され、新しい使用法が反映されています。これは、ビルドシステムやスクリプトが新しい形式に対応する必要があることを示しています。

この変更により、Goのテストフレームワークは、時間指定に関してより堅牢でユーザーフレンドリーなインターフェースを提供するようになりました。

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

src/Make.pkg

--- a/src/Make.pkg
+++ b/src/Make.pkg
@@ -65,7 +65,7 @@ test:
 	gotest
 
 testshort:
-	gotest -test.short -test.timeout=120
+	gotest -test.short -test.timeout=2m
 
 bench:
 	gotest -test.bench=. -test.run="Do not run tests"

src/cmd/go/test.go

--- a/src/cmd/go/test.go
+++ b/src/cmd/go/test.go
@@ -118,8 +118,8 @@ The resulting test binary, called test.out, has its own flags:
 	    the Go tree can run a sanity check but not spend time running
 	    exhaustive tests.
 
-\t-test.timeout n
-\t\tIf a test runs longer than n seconds, panic.
+\t-test.timeout t
+\t\tIf a test runs longer than t, panic.
 
 \t-test.benchtime n
 \t\tRun enough iterations of each benchmark to take n seconds.

src/cmd/gotest/doc.go

--- a/src/cmd/gotest/doc.go
+++ b/src/cmd/gotest/doc.go
@@ -75,7 +75,7 @@ Usage:
 \t\t[-test.cpuprofile=cpu.out] \\\
 \t\t[-test.memprofile=mem.out] [-test.memprofilerate=1] \\\
 \t\t[-test.parallel=$GOMAXPROCS] \\\
-\t\t[-test.timeout=10] [-test.short] \\\
+\t\t[-test.timeout=10s] [-test.short] \\\
 \t\t[-test.benchtime=3] [-test.cpu=1,2,3,4]\n
 The -test.v flag causes the tests to be logged as they run.  The
@@ -117,7 +117,7 @@ time.  It is off by default but set by all.bash so installations of
 the Go tree can do a sanity check but not spend time running
 exhaustive tests.\n
-The -test.timeout flag sets a timeout for the test in seconds.  If the
+The -test.timeout flag sets a timeout for the test.  If the
 test runs for longer than that, it will panic, dumping a stack trace
 of all existing goroutines.

src/pkg/testing/testing.go

--- a/src/pkg/testing/testing.go
+++ b/src/pkg/testing/testing.go
@@ -63,7 +63,7 @@ var (
 	memProfile     = flag.String("test.memprofile", "", "write a memory profile to the named file after execution")
 	memProfileRate = flag.Int("test.memprofilerate", 0, "if >=0, sets runtime.MemProfileRate")
 	cpuProfile     = flag.String("test.cpuprofile", "", "write a cpu profile to the named file during execution")
-\ttimeout        = flag.Int64("test.timeout", 0, "if > 0, sets time limit for tests in seconds")
+\ttimeout        = flag.Duration("test.timeout", 0, "if positive, sets an aggregate time limit for all tests")
 	cpuListStr     = flag.String("test.cpu", "", "comma-separated list of number of CPUs to use for each test")
 	parallel       = flag.Int("test.parallel", runtime.GOMAXPROCS(0), "maximum test parallelism")
 
@@ -346,7 +346,7 @@ var timer *time.Timer
 // startAlarm starts an alarm if requested.
 func startAlarm() {
 	if *timeout > 0 {
-\t\ttimer = time.AfterFunc(time.Duration(*timeout)*time.Second, alarm)
+\t\ttimer = time.AfterFunc(*timeout, alarm)
 	}
 }

コアとなるコードの解説

src/pkg/testing/testing.go

  • timeout = flag.Duration("test.timeout", 0, "if positive, sets an aggregate time limit for all tests"):

    • この行が、-test.timeoutフラグの型をint64からtime.Durationに変更する核心部分です。flag.Duration関数を使用することで、コマンドラインから"10s"や"2m"のような時間文字列を直接受け取り、それをtime.Duration型の変数timeoutにパースして格納するようになります。これにより、時間単位の指定がより直感的になります。
    • コメントも「秒単位でテストの時間制限を設定する」から「すべてのテストの集計時間制限を設定する」に変更され、time.Durationが単一のテストではなく、テストスイート全体の時間制限を意味することが明確化されています。
  • timer = time.AfterFunc(*timeout, alarm):

    • 以前はtime.Duration(*timeout)*time.Secondのように、int64型の*timeouttime.Secondを掛けてtime.Duration型に変換していました。
    • 変更後は、timeout変数がすでにtime.Duration型であるため、*timeoutを直接time.AfterFuncに渡すことができます。これにより、コードが簡潔になり、意図がより明確になります。time.AfterFuncは指定された期間が経過した後にalarm関数を実行するタイマーを設定します。

src/cmd/go/test.go および src/cmd/gotest/doc.go

  • これらのファイルは、go testコマンドおよびgotestコマンドのヘルプメッセージとドキュメントを更新しています。
  • -test.timeoutフラグの説明が「n秒」から「t(期間)」に変更され、新しい時間指定形式(例: "10s")が示されています。これは、ユーザーが新しい形式でタイムアウトを指定する必要があることを明確に伝えるための変更です。

src/Make.pkg

  • testshortターゲットの-test.timeoutの値が120から2mに変更されています。これは、ビルドスクリプトやMakefileのような自動化された環境でも、新しいtime.Duration形式を使用するように更新する必要があることを示す具体的な例です。2mは2分を意味し、以前の120秒と同じ期間を表しますが、より読みやすくなっています。

これらの変更は全体として、Goのテストフレームワークにおけるタイムアウト機能の使いやすさと堅牢性を向上させています。

関連リンク

参考にした情報源リンク