Goテスト入門:実践と品質
Go実践でのテスト入門
Go言語は標準ライブラリに testing パッケージを備えており、テストを書くことが非常に簡単です。まずは go test コマンドを実行して、テストが走る環境を整えましょう。テストファイルは *_test.go という名前で作成し、関数名は TestXxx で始める必要があります。これにより、Goのビルドツールが自動的にテストを検出します。
テスト入門としては、まず簡単な関数を作り、期待値と実際の値を t.Errorf で比較します。失敗した場合にエラーメッセージを出力することで、何が問題かをすぐに把握できます。
testingパッケージの基本
testingパッケージは *testing.T 型を引数に取る関数をテストケースとして扱います。t.Run を使うとサブテストを作成でき、テストの粒度を細かく管理できます。サブテストは並列実行も可能で、t.Parallel() を呼び出すだけで実行されます。
また、テストの前後に共通処理を入れたい場合は TestMain を定義します。TestMain(m *testing.M) はテスト全体のセットアップとクリーンアップを行うために使われ、m.Run() で実際のテストを実行します。
TestMainとt.Runでのテスト構造
以下は TestMain と t.Run を組み合わせたサンプルです。
package main
import (
"os"
"testing"
)
func TestMain(m *testing.M) {
// テスト前のセットアップ
initDB()
code := m.Run()
// テスト後のクリーンアップ
closeDB()
os.Exit(code)
}
func TestExample(t *testing.T) {
t.Run("正常系", func(t *testing.T) {
result := add(1, 2)
if result != 3 {
t.Errorf("期待値 3 だが got %d", result)
}
})
t.Run("異常系", func(t *testing.T) {
result := add(-1, -2)
if result != -3 {
t.Errorf("期待値 -3 だが got %d", result)
}
})
}
この構造により、テストの前後に共通処理をまとめつつ、個別のケースをサブテストで分離できます。
テーブル駆動テストとExample
テーブル駆動テストは、入力と期待値をテーブル(スライス)にまとめてループで実行する手法です。コードの重複を減らし、テストケースを追加しやすくします。
func TestAdd(t *testing.T) {
tests := []struct{
name string
a, b int
want int
}{
{"正の数", 1, 2, 3},
{"負の数", -1, -2, -3},
{"ゼロ", 0, 0, 0},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := add(tt.a, tt.b); got != tt.want {
t.Errorf("add(%d,%d) = %d; want %d", tt.a, tt.b, got, tt.want)
}
})
}
}
さらに、Example 関数を使うと、ドキュメントコメントと実行結果を自動で検証できます。go test が実行時に期待される出力と実際の出力を比較し、ドキュメントの正確性を保証します。
func ExampleAdd() {
fmt.Println(add(1, 2))
// Output: 3
}
カバレッジとベンチマークで品質を測る
テストだけでなく、コードのカバレッジを確認することで、未テスト領域を可視化できます。go test -coverprofile=coverage.out でプロファイルを生成し、go tool cover -html=coverage.out で可視化します。
また、ベンチマークテストは func BenchmarkXxx(b *testing.B) で書き、go test -bench=. で実行します。ベンチマークはパフォーマンスのボトルネックを特定し、品質向上に直結します。
総合的に見ると、Go実践におけるテスト入門から始め、testingパッケージの機能を駆使し、TestMainやt.Runで構造化し、テーブル駆動テストとExampleで可読性とドキュメント性を高め、最後にカバレッジとベンチマークで品質を定量的に測定する流れが理想的です。
コメント
コメントを投稿