go-testing について
Go 開発者向けのテストスキルです。テストパターン、ヘルパー、比較方法、統合テストの指針に加え、雛形生成スクリプトとテンプレートを提供します。
主な機能
- 01テーブル駆動テストとサブテストの指針
- 02テストヘルパー、フィクスチャ、クリーンアップのパターン
- 03入力、実際値、期待値を含む失敗メッセージ
- 04意味に基づくエラーチェックと比較方法
- 05雛形生成スクリプトとテストテンプレート
活用シーン
- 01テーブル駆動テストケースの作成
- 02確実に後処理するテストヘルパーの作成
- 03HTTP ハンドラー、データベース、外部サービスのテスト
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ cxuu/ golang-skills --skill go-testingインストール後、Claude Code で/go-testingを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
assets/table-test-template.goreferences/INTEGRATION.mdTABLE-DRIVEN-TESTS.mdTEST-HELPERS.mdTEST-ORGANIZATION.mdVALIDATION-APIS.mdscripts/gen-table-test.sh詳細
Go Testing
互換性:Diff の例では
github.com/google/go-cmpを使用する場合があります。
リソースルーティング
scripts/gen-table-test.sh- テーブル駆動テストのひな形を生成するときに実行します。assets/table-test-template.go- コピーして使えるテーブルテストの出発点として使用します。references/TABLE-DRIVEN-TESTS.md- テーブルテスト、サブテスト、並列テストのパターンを選ぶときに参照します。references/TEST-HELPERS.md- ヘルパー、フィクスチャ、クリーンアップ、テストダブルを作成するときに参照します。references/TEST-ORGANIZATION.md- パッケージ、ブラックボックステスト、大規模なテストスイートを構成するときに参照します。references/VALIDATION-APIS.md-t.Error、t.Fatal、cmp.Diff、アサーションのスタイルを選ぶときに参照します。references/INTEGRATION.md- 外部サービス、HTTP ハンドラー、データベース、または長時間かかるセットアップをテストするときに参照します。
クイックリファレンス
| パターン | 使用する場面 |
|---|---|
t.Error | デフォルト — 失敗を報告し、テストを続行します |
t.Fatal | セットアップに失敗した場合、または続行しても意味がない場合 |
cmp.Diff | 構造体、スライス、マップ、proto の比較 |
| テーブル駆動 | 多くのケースで同じロジックを共有する場合 |
| サブテスト | フィルタリング、並列実行、または名前付けが必要な場合 |
t.Helper() | すべてのテストヘルパー関数(最初の文として呼び出します) |
t.Cleanup() | defer ではなく、ヘルパー内で後処理を行う場合 |
役立つテスト失敗メッセージ
規範:テストの失敗は、テストのソースを読まなくても診断できなければなりません。
すべての失敗メッセージには、関数名、入力値、実際の値(got)、期待値(want)を含めてください。形式は YourFunc(%v) = %v, want %v を使用します。
// Good:
t.Errorf("Add(2, 3) = %d, want %d", got, 5)
// Bad: Missing function name and inputs
t.Errorf("got %d, want %d", got, 5)
got は常に want より先に出力してください:got %v, want %v — 順序を逆にしてはいけません。
アサーションライブラリは使用しない
規範:アサーションライブラリは使用しないでください。複雑な比較には
cmp.Diffを使用します。
if diff := cmp.Diff(want, got); diff != "" {
t.Errorf("GetPost() mismatch (-want +got):\n%s", diff)
}
プロトコルバッファでは、cmp オプションとして protocmp.Transform() を追加してください。差分メッセージには、方向を示すキー (-want +got) を必ず含めてください。JSON/シリアライズ済みの出力を比較するのではなく、意味に基づいて比較してください。
t.Error と t.Fatal
規範:1 回の実行ですべての失敗を報告できるよう、デフォルトでは
t.Errorを使用してください。t.Fatalは続行できない場合に限って使用します。
t.Fatal を選ぶ場合:
- セットアップに失敗した(DB 接続、ファイル読み込み)
- 次のアサーションが、前のアサーションの成功を前提としている(例:エンコード後のデコード)
テストのゴルーチン以外のゴルーチンから t.Fatal/t.FailNow を呼び出してはいけません。代わりに t.Error を使用してください。
テーブル駆動テスト
新しいテーブル駆動テストのひな形を作成するときや、標準的な構造体、ループ、サブテストの構成が必要なときは、
assets/table-test-template.goを参照してください。
推奨:多くのケースで同じロジックを共有する場合は、テーブル駆動テストを使用してください。
テーブルテストを使用する場合: 条件付きのセットアップ、モック、アサーションを必要とせず、すべてのケースで同じコードパスを実行する場合です。shouldErr という単一の bool は使用してもかまいません。
テーブルテストを使用しない場合: ケースごとに複雑なセットアップ、条件付きのモック、または複数の分岐が必要な場合は、代わりに個別のテスト関数を作成してください。
主なルール:
- ケースが複数行にわたる場合、または同じ型のフィールドが隣接する場合は、フィールド名を使用します
- 失敗メッセージには入力値を含めてください — 行をインデックスで特定してはいけません
検証:テストを生成または変更した後、
go test -run TestXxx -vを実行して、テストがコンパイルされ、パスすることを確認してください。先に進む前に、コンパイルエラーを修正してください。
テストヘルパー
規範:テストヘルパーでは最初に
t.Helper()を呼び出し、後処理にはt.Cleanup()を使用してください。
func setupTestDB(t *testing.T) *sql.DB {
t.Helper()
db, err := sql.Open("sqlite3", ":memory:")
if err != nil {
t.Fatalf("Could not open database: %v", err)
}
t.Cleanup(func() { db.Close() })
return db
}
テストのエラーセマンティクス
推奨:エラーメッセージの文字列ではなく、エラーのセマンティクスをテストしてください。
// Bad: Brittle string comparison
if err.Error() != "invalid input" { ... }
// Good: Semantic check
if !errors.Is(err, ErrInvalidInput) { ... }
特定のセマンティクスが重要ではない場合の、単純な存在確認には次を使用します。
if gotErr := err != nil; gotErr != tt.wantErr {
t.Errorf("f(%v) error = %v, want error presence = %t", tt.input, err, tt.wantErr)
}
関連するスキル
- エラーのテスト:
errors.Is/errors.Asまたはセンチネルエラーを使ってエラーの意味をテストする場合は、go-error-handling を参照してください - インターフェースのモック:利用側でインターフェースを実装してテストダブルを作成する場合は、go-interfaces を参照してください
- テスト関数の命名:テスト関数、サブテスト、テストヘルパーユーティリティに名前を付ける場合は、go-naming を参照してください
- リンターの統合:CI またはコミット前フックでテストと併せてリンターを実行する場合は、go-linting を参照してください