🧪
【Go】Goのテストに入門してみた! ~Table Driven Test編~
はじめに
前回は、Goにおけるテストの基本を学びました。
今回は、Goでよく使われる 「テーブル駆動テスト(Table Driven Test)」 に入門します。
前回の記事はこちら↓
この記事でわかること
- Table Driven Testの概要
- 実装方法
- 実装時に押さえておきたいポイント
実装してみた
前回に引き続き、マルチバイトでの文字列カウントについてのテストケースを見ていきます。
main_test.go
package main
import (
"testing"
"unicode/utf8"
)
func Length(s string) int {
return utf8.RuneCountInString(s)
}
func TestLength(t *testing.T) {
tests := []struct {
name string
input string
want int
}{
{"ascii", "Hello", 5},
{"full-width-japanese", "こんにちは", 5},
{"half-width-japanese", "コンニチハ", 5},
{"emoji", "😃😃😃", 3},
{"empty", "", 0},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := Length(tt.input); got != tt.want {
t.Errorf("Length = %d, want %d", got, tt.want)
}
})
}
}
実行してみると、以下のような結果が得られます。
ターミナル
# go test -v
# -vフラグをつけることで詳細なテスト結果を得ることができる
=== RUN TestLength
=== RUN TestLength/ascii
=== RUN TestLength/full-width-japanese
=== RUN TestLength/half-width-japanese
=== RUN TestLength/emoji
=== RUN TestLength/empty
--- PASS: TestLength (0.00s)
--- PASS: TestLength/ascii (0.00s)
--- PASS: TestLength/full-width-japanese (0.00s)
--- PASS: TestLength/half-width-japanese (0.00s)
--- PASS: TestLength/emoji (0.00s)
--- PASS: TestLength/empty (0.00s)
PASS
ok go-test-practice 0.192s
押さえておきたいポイント
1. 構造体を作成する
テーブル駆動テストでは、「入力値」と「期待される出力値」の一覧表(テーブル) を作成します。
Goではこのテーブルを構造体のスライスで表現し、ループで1件ずつテストを実行するのが一般的です。
テストケースを一か所に集約することで、可読性と保守性が高まります。
2. テスト名をつける
各テストケースにテスト名があることで、どのテストで失敗したのかがわかりやすくなります。
特にテストケースが多い時に効力を発揮します。
3. t.Run()でテストを実行
testingパッケージのRunメソッドを使うことで、各テストケースを個別のサブテストとして実行できます。
- 第1引数:サブテスト名(上で定義した
name) - 第2引数:サブテストの処理を記述した無名関数(
func(t *testing.T))
こうすることで、個別に失敗を追跡できるだけでなく、特定のテストだけを選んで実行することも可能になります。
4. 期待値と実際の値
変数名として、期待値にはwantを、実際の値にはgotを使うことが一般的です。
テスト結果のログが読みやすくなり、テストの意図も明確になります。
まとめ
今回は、Goでのテーブル駆動テストの基本を学びました。
- テストケースを構造体のスライスで定義し
-
t.Run()で各ケースをサブテストとして実行することで - 簡潔かつ拡張性の高いテストコードを書くことができることが分かりました。
次回は、特定のサブテストのみを実行する方法についてみていきます。
参考
Discussion