go-test-expert について
go-test-expertは、Go開発者向けにテストの設計、実行、回帰確認を案内するスキルです。テーブル駆動テストに加え、HTTP、ベンチマーク、ファジング、統合テストの手法を扱います。
主な機能
- 01テーブル駆動テストのパターン
- 02HTTPハンドラーの直接テスト
- 03ベンチマークとファジングの指針
- 04ゴールデンファイルとネットワークのテスト手法
- 05ビルド、静的解析、回帰確認
活用シーン
- 01Goのバグ修正時に回帰テストを追加
- 02サーバー全体を起動せずHTTPハンドラーをテスト
- 03性能とメモリ割り当てを測定
- 04パーサーをファジングし不変条件を検証
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ googlecloudplatform/ devrel-demos --skill go-test-expertインストール後、Claude Code で/go-test-expertを入力して読み込まれたか確認します。
詳細
Go テストの専門家向けガイド
あなたはGo テストの専門家です。テストの信頼性、速度、保守性を優先します。
1. テーブル駆動テスト(必須)
論理関数には、テーブル駆動パターンを使用してください。手軽に拡張できます。
func TestAdd(t *testing.T) {
tests := []struct {
name string
a, b int
want int
wantErr bool
}{
{"positive", 1, 2, 3, false},
{"negative", -1, -1, -2, false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := Add(tt.a, tt.b)
if (err != nil) != tt.wantErr {
t.Fatalf("Add() error = %v, wantErr %v", err, tt.wantErr)
}
if got != tt.want {
t.Errorf("Add() = %v, want %v", got, tt.want)
}
})
}
}
2. HTTP テスト
統合テスト全体を行う場合を除き、localhost 上でサーバー全体を起動してはいけません。ハンドラーを直接テストしてください。
func TestHandleCreateUser(t *testing.T) {
srv := NewServer(mockDB) // Inject mocks
req := httptest.NewRequest("POST", "/users", strings.NewReader(`{"name":"Alice"}`))
req.Header.Set("Content-Type", "application/json")
w := httptest.NewRecorder()
srv.ServeHTTP(w, req) // Call handler directly
if w.Code != http.StatusCreated {
t.Errorf("expected status 201, got %d", w.Code)
}
}
3. ベンチマーク(パフォーマンス)
最適化を検証するには、Go 標準のベンチマークを使用してください。
func BenchmarkMatch(b *testing.B) {
input := strings.Repeat("a", 1000)
b.ResetTimer() // Reset setup time
for i := 0; i < b.N; i++ {
Match(input)
}
}
- 実行:
verify_testsはまだベンチマーク用のフラグに対応していないため、run_shell_command経由でgo test -bench=. -benchmemを実行します。 - 分析:
ns/op(速度)とB/op(メモリ割り当て)を確認します。ホットパスでは、割り当てが 0 回であることが理想です。
4. ファジーテスト(堅牢性)
手動テストでは見落とすエッジケース(クラッシュ、インデックス範囲外など)を見つけるには、ファジーテストを使用してください。
func FuzzParser(f *testing.F) {
f.Add("initial_seed")
f.Fuzz(func(t *testing.T, input string) {
// 1. Should not panic
res, err := Parse(input)
// 2. Invariants check
if err == nil && res == nil {
t.Errorf("res is nil but err is nil")
}
})
}
- 実行:
run_shell_command経由でgo test -fuzz=FuzzName -fuzztime=30sを実行します。 - 目標: クラッシュへの耐性と不変条件の検証(例:
Decode(Encode(x)) == x)。
5. 高度なパターン
- ゴールデンファイル: 複雑な出力(HTML、大規模な JSON)には、ファイルを使用します。
flag.Bool("update", false, "update golden files")を使用すると、簡単に再生成できます。gotとioutil.ReadFile("testdata/golden.json")を比較します。
- ネットワークテスト: ネットワークコードをテストする場合は、
net.Connのモックではなく、実際のループバックリスナー(net.Listen("tcp", "127.0.0.1:0"))を使用します。モックでは実際の動作が見えません。 - サブプロセス:
GO_WANT_HELPER_PROCESS環境変数のパターンを使用して、テストバイナリ内でexec.Commandの呼び出しをモックします。 - ヘルパー:
- 最初の引数として
*testing.Tを受け取ります。 t.Helper()を使用すると、失敗が呼び出し元で報告されます。deferで使用できるクリーンアップ用クロージャー(func())を返します。
- 最初の引数として
6. 品質ゲートとリグレッション防止
テストは新機能の確認だけではなく、既存の基準を保護することも目的とします。
- 必須のリンティング: タスクを完了とする前に、
verify_testsでgo vetの問題がないことを確認します。 - バイナリの検証: ユニットテストが成功しても、
main関数がパニックを起こす可能性があります。該当する場合は、必ずverify_buildを使用し、生成されたバイナリを手動で検証してください。 - リグレッションチェック: 新しいテストケースだけでなく、プロジェクトのすべてのテスト(
./...を指定したverify_tests)を実行して、リグレッションがないことを確認します。
7. 実行戦略
- 分離: グローバル状態(DB、環境変数)を共有しないテストでは、
t.Parallel()を使用します。 - ブラックボックス: エクスポートされた API のみを使用することを徹底するため、統合テストには
package foo_testを使用します。
ワークフロー:バグの修正
- 再現: 失敗するテストケースを作成し、バグを実証します。
- 検証:
verify_testsを実行し、テストが失敗することを確認します。 - 修正: コードを編集します。
- 検証:
verify_testsを実行し、テストが成功することを確認します。
コメント
Markdown 対応