【Go言語】テーブルドリブンテストの実践的な実装方法と活用例
こんにちは!フリーランスエンジニアのこたろうです。
Go言語での開発において、効率的なテスト実装は非常に重要です。今回は、実際のプロジェクト例を用いながら、テーブルドリブンテストの実装方法とその活用について解説します。
テーブルドリブンテストとは?
テーブルドリブンテストは、テストケースをデータとして管理し、反復的に処理することでコードを簡潔かつ明瞭に記述するテスト手法です。この手法を使うことで、テストケースの追加や修正が容易になり、コードの保守性も向上します。
テストの基本的な流れ
テーブルドリブンテストは、以下の3つのステップで実装します:
- テストケース名とテストデータのスライスを作成
- for文でスライスをループ処理
- サブテストの実行
実装例
今回は、記事の一覧・詳細を取得する簡易ブログシステムを例に説明します。
1. テストの前処理・後処理
package repositories_test
import (
"database/sql"
"fmt"
"os"
"testing"
_ "github.com/go-sql-driver/mysql"
)
var testDB *sql.DB
func TestMain(m *testing.M) {
// 前処理
if err := setup(); err != nil {
fmt.Println("Failed to set up test environment:", err)
os.Exit(1)
}
// テスト実行
code := m.Run()
// 後処理
teardown()
os.Exit(code)
}
func setup() error {
dbUser := "hogeuser"
dbPassword := "hogepass"
dbDatabase := "hogedb"
dbConn := fmt.Sprintf("%s:%s@tcp(127.0.0.1:3306)/%s?parseTime=true",
dbUser, dbPassword, dbDatabase)
var err error
testDB, err = sql.Open("mysql", dbConn)
return err
}
func teardown() {
testDB.Close()
}
2. 通常のテスト実装例
func TestSelectArticleList(t *testing.T) {
expectedNum := 3
got, err := repositories.SelectArticleList(testDB, 1)
if err != nil {
t.Fatal(err)
}
if len(got) != expectedNum {
t.Errorf("Expected %d articles, but got %d", expectedNum, len(got))
}
}
3. テーブルドリブンテストの実装例
func TestSelectArticleDetail(t *testing.T) {
tests := []struct {
testTitle string
expected models.Article
}{
{
testTitle: "正常系:最初の投稿を取得",
expected: models.Article{
ID: 1,
Title: "firstPost",
Contents: "This is my first blog",
UserName: "ikeda",
NiceNum: 3,
},
},
{
testTitle: "正常系:2番目の投稿を取得",
expected: models.Article{
ID: 2,
Title: "2nd",
Contents: "Second blog post",
UserName: "ikeda",
NiceNum: 4,
},
},
}
for _, test := range tests {
t.Run(test.testTitle, func(t *testing.T) {
got, err := repositories.SelectArticleDetail(testDB, test.expected.ID)
if err != nil {
t.Fatal(err)
}
if got.ID != test.expected.ID {
t.Errorf("Expected ID %d, but got %d",
test.expected.ID, got.ID)
}
if got.Title != test.expected.Title {
t.Errorf("Expected Title %s, but got %s",
test.expected.Title, got.Title)
}
// その他のフィールドの検証も同様に実装
})
}
}
実装のポイント
-
テストケースの構造体定義
- テストケースごとに期待値と入力値を明確に定義
- テストケース名は具体的な内容を記述
-
サブテストの活用
-
t.Run
を使用して各テストケースを独立して実行 - テスト失敗時に該当するケースが特定しやすい
-
-
エラーメッセージの充実
- 期待値と実際の値を明確に表示
- どのフィールドで失敗したかを具体的に示す
テストの実行方法
# 詳細な出力でテストを実行
go test -v
# 特定のテストのみを実行
go test -v -run TestSelectArticleDetail
実行結果の例:
=== RUN TestSelectArticleDetail
=== RUN TestSelectArticleDetail/正常系:最初の投稿を取得
--- PASS: TestSelectArticleDetail/正常系:最初の投稿を取得 (0.01s)
=== RUN TestSelectArticleDetail/正常系:2番目の投稿を取得
--- PASS: TestSelectArticleDetail/正常系:2番目の投稿を取得 (0.01s)
PASS
まとめ
テーブルドリブンテストのメリット:
- テストケースの追加・修正が容易
- コードの重複を防ぎ、保守性が向上
- テスト結果が明確で理解しやすい
- 複数のパターンを効率的にテスト可能
この手法を活用することで、より堅牢なテストを効率的に実装することができます。ぜひ、みなさんのプロジェクトでも取り入れてみてください!
参考文献
- 『Goで作るはじめてのWebアプリケーション 改訂版』技術書典