Golang でよく利用する testing まとめ
Go 言語には標準で testing
パッケージが用意されており、ユニットテストやベンチマークテストを簡単に記述できます。本記事では、Golang のテストでよく利用するテクニックをまとめます。
1. testing
パッケージの基本
Go では、testing
パッケージを使ってテストを書くのが一般的です。基本的なテストの書き方は以下の通りです。
package main
import (
"testing"
)
func Add(a, b int) int {
return a + b
}
func TestAdd(t *testing.T) {
result := Add(2, 3)
if result != 5 {
t.Errorf("Expected 5, but got %d", result)
}
}
テスト関数の命名は TestXxx
という形式にする必要があります。go test
コマンドを実行すると、このテストが自動的に実行されます。
2. テーブル駆動テスト
テーブル駆動テストとは、複数のテストケースをまとめて定義し、それをループで処理するテストの手法です。
func TestAddTableDriven(t *testing.T) {
tests := []struct {
a, b, expected int
}{
{1, 1, 2},
{2, 3, 5},
{10, 5, 15},
}
for _, tt := range tests {
result := Add(tt.a, tt.b)
if result != tt.expected {
t.Errorf("Add(%d, %d) = %d; want %d", tt.a, tt.b, result, tt.expected)
}
}
}
テストケースを増やしやすく、可読性も向上するため、実践的なコードではテーブル駆動テストをよく使います。
3. setup
/ teardown
処理
テストの前後に準備や後処理が必要な場合は、TestMain
を使うことができます。
func TestMain(m *testing.M) {
// テスト前のセットアップ処理
setup()
// テスト実行
exitCode := m.Run()
// テスト後のクリーンアップ処理
teardown()
// テストの終了コードを返す
os.Exit(exitCode)
}
4. t.Helper()
を活用する
ヘルパー関数を定義する際には t.Helper()
を使うことで、エラーメッセージの出力時にヘルパー関数を無視して呼び出し元の情報を表示できます。
func assertEqual(t *testing.T, got, want int) {
t.Helper() // ヘルパー関数であることを明示
if got != want {
t.Errorf("Expected %d, but got %d", want, got)
}
}
5. mock
を用いたテスト
依存関係をモック化してテストする場合、interface
を利用すると便利です。
type UserRepository interface {
FindByID(id int) string
}
type MockUserRepository struct{}
func (m *MockUserRepository) FindByID(id int) string {
return "mock_user"
}
func TestMockRepository(t *testing.T) {
mockRepo := &MockUserRepository{}
user := mockRepo.FindByID(1)
if user != "mock_user" {
t.Errorf("Expected mock_user, but got %s", user)
}
}
6. httptest
を用いた HTTP ハンドラのテスト
Go の net/http/httptest
パッケージを使うと、HTTP ハンドラのテストを簡単に実装できます。
func HelloHandler(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Write([]byte("Hello, World!"))
}
func TestHelloHandler(t *testing.T) {
req := httptest.NewRequest("GET", "http://example.com/hello", nil)
w := httptest.NewRecorder()
HelloHandler(w, req)
resp := w.Result()
body, _ := io.ReadAll(resp.Body)
if resp.StatusCode != http.StatusOK {
t.Errorf("Expected status 200, but got %d", resp.StatusCode)
}
if string(body) != "Hello, World!" {
t.Errorf("Unexpected response body: %s", body)
}
}
まとめ
Golang の testing
パッケージを活用すると、簡単にユニットテストや統合テストを記述できます。本記事で紹介した内容を活用し、より堅牢なコードを実装しましょう。
- 基本的な
TestXxx
関数の作成 - テーブル駆動テストの活用
-
setup
/teardown
の処理 (TestMain
) -
t.Helper()
を使ったヘルパー関数 -
mock
による依存関係のテスト -
httptest
による HTTP ハンドラのテスト
Go のテストを効率よく書き、バグの少ないアプリケーションを目指しましょう!