[インデックス 19568] ファイルの概要
このコミットは、Go言語の標準ライブラリであるtesting
パッケージにおけるテストおよびExampleの実行時間表示形式の不整合を修正するものです。具体的には、時間の表示形式を統一し、より機械的に解析しやすい形式に改善しています。
コミット
commit 0e92b538a9f6e337b8e48f47f38803e8245c03cc
Author: Robert Dinu <r@varp.se>
Date: Wed Jun 18 10:59:25 2014 -0700
testing: fix timing format inconsistency
Fixes #8175.
LGTM=r
R=golang-codereviews, r, gobot
CC=golang-codereviews
https://golang.org/cl/103320043
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/0e92b538a9f6e337b8e48f47f38803e8245c03cc
元コミット内容
このコミットは、Goのtesting
パッケージにおける時間表示形式の不整合を修正することを目的としています。具体的には、Issue #8175で報告された問題を解決します。
変更の背景
Goのtesting
パッケージは、ユニットテストやExampleの実行結果を表示する際に、テストやExampleの実行にかかった時間を表示します。しかし、この時間の表示形式が、テストとExampleの間で一貫性がなく、また、場合によっては人間が読みやすい形式(例: 1m30s
)と、より厳密な数値形式(例: 90.00s
)が混在していました。
このような不整合は、特にテスト結果を自動的に解析するツールやスクリプトにとって問題となります。形式が一定でないと、正確な時間情報を抽出することが困難になるため、統一されたフォーマットが求められていました。
この問題はIssue #8175として報告され、このコミットはその解決のために行われました。Go Code Review (CL 103320043)での議論を経て、"%.2fs"
という形式で秒単位の時間を小数点以下2桁まで表示する形式に統一することが決定されました。
前提知識の解説
go test
コマンド: Go言語のテストを実行するためのコマンドです。プロジェクトのルートディレクトリでgo test
を実行すると、テストファイル(ファイル名が_test.go
で終わるファイル)内のテスト関数(関数名がTest
で始まる関数)やExample関数(関数名がExample
で始まる関数)が実行されます。testing
パッケージ: Go言語に組み込まれているテストフレームワークを提供するパッケージです。testing.T
型はテスト関数に、testing.B
型はベンチマーク関数に、そしてtesting.Example
型はExample関数に渡され、テストの実行、結果の報告、ヘルパー関数の提供などを行います。time.Duration
型:time
パッケージで定義されている型で、時間の長さを表します。内部的にはナノ秒単位の整数で表現されます。time.Duration
型の値は、String()
メソッドを呼び出すことで人間が読みやすい形式(例:1h2m3s
)に変換できますが、このコミットでは特定の数値形式での出力が求められました。fmt.Sprintf
関数:fmt
パッケージで提供される関数で、指定されたフォーマット文字列に従って値を整形し、文字列として返します。C言語のsprintf
に似ています。このコミットでは、"%.2fs"
というフォーマット文字列を使用して、time.Duration
の秒数を小数点以下2桁まで表示する形式に整形しています。
技術的詳細
このコミットの技術的な核心は、テストおよびExampleの実行時間表示を統一するために、testing
パッケージ内に新しいヘルパー関数fmtDuration
を導入し、既存のコードで時間の表示を行っていた箇所をこの関数を使用するように変更した点です。
以前は、time.Duration
型の値を直接fmt.Printf
に渡したり、duration.Seconds()
の結果を直接フォーマットしたりしていました。これにより、出力形式にばらつきが生じていました。
新しいfmtDuration
関数は以下のようになっています。
// fmtDuration returns a string representing d in the form "87.00s".
func fmtDuration(d time.Duration) string {
return fmt.Sprintf("%.2fs", d.Seconds())
}
この関数は、time.Duration
型の引数d
を受け取り、そのSeconds()
メソッドを呼び出して秒単位の浮動小数点数に変換します。その後、fmt.Sprintf("%.2fs", ...)
を使用して、この秒数を小数点以下2桁の浮動小数点数として整形し、末尾にs
(秒)を付けた文字列を返します。例えば、87.12345s
のようなDurationは"87.12s"
と表示されます。
このfmtDuration
関数が導入されたことで、src/pkg/testing/example.go
とsrc/pkg/testing/testing.go
内の、テストやExampleの実行時間を表示するすべての箇所で、この統一されたフォーマットが適用されるようになりました。これにより、出力の不整合が解消され、機械的な解析が容易になりました。
コアとなるコードの変更箇所
このコミットによって変更された主要なファイルとコード箇所は以下の通りです。
-
src/pkg/testing/example.go
: Exampleの実行結果を報告するrunExample
関数内で、実行時間の表示形式が変更されました。- 変更前:
fmt.Printf("--- FAIL: %s (%v)\\n%s", eg.Name, d, fail)
のように、time.Duration
型のd
を直接%v
で表示していた。 - 変更後:
dstr := fmtDuration(time.Now().Sub(start))
でfmtDuration
を呼び出し、fmt.Printf("--- FAIL: %s (%s)\\n%s", eg.Name, dstr, fail)
のように、dstr
(整形済みの文字列)を使用するように変更。
- 変更前:
-
src/pkg/testing/testing.go
:- 新しいヘルパー関数
fmtDuration
が追加されました。 testing.T
型のreport
メソッド内で、テスト結果を報告する際の実行時間の表示形式が変更されました。- 変更前:
tstr := fmt.Sprintf("(%.2f seconds)", t.duration.Seconds())
のように、秒数を"%.2f seconds"
で表示していた。 - 変更後:
dstr := fmtDuration(t.duration)
でfmtDuration
を呼び出し、format := "--- %s: %s (%s)\\n%s"
とフォーマット文字列も変更し、fmt.Printf(format, "FAIL", t.name, dstr, t.output)
のように、dstr
(整形済みの文字列)を使用するように変更。
- 変更前:
- 新しいヘルパー関数
コアとなるコードの解説
src/pkg/testing/testing.go
におけるfmtDuration
関数の追加
// fmtDuration returns a string representing d in the form "87.00s".
func fmtDuration(d time.Duration) string {
return fmt.Sprintf("%.2fs", d.Seconds())
}
この関数は、time.Duration
型の値を秒単位の浮動小数点数に変換し、それを小数点以下2桁まで表示する"%.2fs"
という形式の文字列に整形します。これにより、テストやExampleの実行時間が常に統一された形式で出力されるようになります。
src/pkg/testing/example.go
における変更
runExample
関数は、Exampleの実行を管理し、その結果を標準出力に報告します。以前は、実行時間をtime.Duration
型のデフォルトの文字列表現(%v
フォーマット)で出力していましたが、これは秒単位の精度が一定ではありませんでした。
// 変更前
// d := time.Now().Sub(start)
// fmt.Printf("--- FAIL: %s (%v)\\n%s", eg.Name, d, fail)
// 変更後
dstr := fmtDuration(time.Now().Sub(start)) // 新しいfmtDuration関数を使用
fmt.Printf("--- FAIL: %s (%s)\\n%s", eg.Name, dstr, fail)
この変更により、Exampleの実行時間も"87.00s"
のような統一された形式で表示されるようになりました。
src/pkg/testing/testing.go
におけるreport
メソッドの変更
report
メソッドは、個々のテスト(*testing.T
)の最終結果(PASS/FAIL/SKIP)を報告する際に呼び出されます。以前は、t.duration.Seconds()
を直接fmt.Sprintf
でフォーマットしていましたが、このコミットではfmtDuration
関数を使用するように変更されました。
// 変更前
// tstr := fmt.Sprintf("(%.2f seconds)", t.duration.Seconds())
// format := "--- %s: %s %s\\n%s"
// fmt.Printf(format, "FAIL", t.name, tstr, t.output)
// 変更後
dstr := fmtDuration(t.duration) // 新しいfmtDuration関数を使用
format := "--- %s: %s (%s)\\n%s" // フォーマット文字列も変更
fmt.Printf(format, "FAIL", t.name, dstr, t.output)
この変更により、テストの実行時間もExampleと同様に"87.00s"
のような統一された形式で表示されるようになり、testing
パッケージ全体での時間表示の一貫性が確保されました。
関連リンク
- GitHubコミットページ: https://github.com/golang/go/commit/0e92b538a9f6e337b8e48f47f38803e8245c03cc
- Go Code Review (CL 103320043): https://golang.org/cl/103320043
参考にした情報源リンク
- Go Code Review (CL 103320043) の内容
- Go言語の
testing
パッケージに関する一般的なドキュメント - Go言語の
time
パッケージに関する一般的なドキュメント - Go言語の
fmt
パッケージに関する一般的なドキュメント - Web検索: "Go testing package timing format inconsistency"
- Web検索: "Go issue 8175" (直接的な結果は得られなかったが、CLの情報を補完するために使用)