Goテスト: testifyで
はじめに
Goでのユニットテスト実践は、コードの品質を保つために不可欠です。この記事では、testifyを中心に、assertとrequireの使い分け、mockの導入、テスト補助関数による効率化、そして可読性を高めるテクニックを紹介します。Go実践の観点から、実際に書くコード例とともに解説します。
testifyの基本
testifyはGoで最も人気のあるテストフレームワークの一つです。assertとrequireパッケージを使うことで、テストコードを簡潔に書けます。まずはインストール例です。
go get github.com/stretchr/testify
テスト関数内でassertを使うと、失敗しても残りのテストが実行されます。requireは失敗すると直ちにテストを停止します。これにより、前提条件が満たされないケースで無駄な処理を避けられます。
assert vs require
以下のように使い分けると、テストの可読性と効率化が向上します。
func TestExample(t *testing.T) {
assert := assert.New(t)
require := require.New(t)
// 前提条件チェック
require.NotNil(t, db, "DB should be initialized")
// 実際の検証
assert.Equal(t, 42, result, "Result should be 42")
}
assertは結果を確認しつつ、テストを継続。requireは失敗時に即座に停止。これにより、テストの失敗原因を早期に特定できます。
mockの活用
外部依存を切り離すために、mockを使うことが重要です。testifyのmockパッケージを利用すると、インターフェースを簡単にモックできます。
type UserRepository interface {
FindByID(ctx context.Context, id int) (*User, error)
}
type MockUserRepo struct {
mock.Mock
}
func (m *MockUserRepo) FindByID(ctx context.Context, id int) (*User, error) {
args := m.Called(ctx, id)
return args.Get(0).(*User), args.Error(1)
}
テストではOnで期待値を設定し、AssertExpectationsで呼び出しを検証します。これにより、実際のデータベースにアクセスせずにロジックを検証できます。
テスト補助関数で効率化
共通のセットアップやクリーンアップを関数化すると、テストコードがすっきりします。例えば、以下のようにsetupTestDBを作成します。
func setupTestDB(t *testing.T) (*sql.DB, func()) {
db, err := sql.Open("sqlite3", ":memory:")
require.NoError(t, err)
// テーブル作成
_, err = db.Exec(`CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)`)
require.NoError(t, err)
cleanup := func() {
db.Close()
}
return db, cleanup
}
テスト関数内で呼び出すだけで、DBの初期化とクリーンアップが自動化されます。
可読性を保つコツ
テストコードは実装コードと同様に可読性が重要です。以下のポイントを意識しましょう。
- テスト名は何を検証しているかを明示的に書く(例:
TestCreateUser_Success) - 期待値と実際値を分かりやすくコメントで補足
- 共通ロジックはテスト補助関数に切り出す
- assert/requireの呼び出しは一行で完結させる
これらを実践することで、チーム全体でテストコードを読みやすく、保守しやすくなります。
まとめ
Go実践におけるユニットテストは、testifyのassertとrequire、mockを組み合わせることで、効率化と可読性を両立できます。テスト補助関数を活用し、共通処理を整理することで、テストコードの量を減らし、バグ検出の速度を上げることが可能です。ぜひこの記事の例を参考に、プロジェクトに導入してみてください。
コメント
コメントを投稿