[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M72XSPZSCRBFSGGT36CFKK4F":3,"skill-same:01M72XSPZSCRBFSGGT36CFKK4F":47},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":19,"linkOnly":20,"markdownContent":21,"markdownBody":22,"frontMatter":23,"refName":24,"commitSha":25,"skillDirectory":26,"forksCount":27,"repositoryHtmlUrl":28,"repositoryHomepageUrl":6,"ownerHtmlUrl":29,"ownerBlogUrl":30,"ownerDescription":31,"updatedAt":32,"install":33,"resources":46},"01M72XSPZSCRBFSGGT36CFKK4F","golang-testing",null,"テスト駆動開発とGoコードの高品質を保証するための包括的なテスト戦略。","SriramGandhiS\u002FSkills","SriramGandhiS","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F211849986?v=4","01M72WQCW12BYX71C6WN584TTA","Sriram S","01M72WQCWTJ2RD0ET1X31AF1RC",1,"MIT","https:\u002F\u002Fgithub.com\u002FSriramGandhiS\u002FSkills\u002Fblob\u002Fmaster\u002Feverything-claude-code\u002Fdocs\u002Fja-JP\u002Fskills\u002Fgolang-testing\u002FSKILL.md",[],[],"2026-11-10 22:39:42",false,"---\nname: golang-testing\ndescription: テスト駆動開発とGoコードの高品質を保証するための包括的なテスト戦略。\n---\n\n# Go テスト\n\nテスト駆動開発(TDD)とGoコードの高品質を保証するための包括的なテスト戦略。\n\n## いつ有効化するか\n\n- 新しいGoコードを書くとき\n- Goコードをレビューするとき\n- 既存のテストを改善するとき\n- テストカバレッジを向上させるとき\n- デバッグとバグ修正時\n\n## 核となる原則\n\n### 1. テスト駆動開発(TDD)ワークフロー\n\n失敗するテストを書き、実装し、リファクタリングするサイクルに従います。\n\n```go\n\u002F\u002F 1. テストを書く（失敗）\nfunc TestCalculateTotal(t *testing.T) {\n    total := CalculateTotal([]float64{10.0, 20.0, 30.0})\n    want := 60.0\n    if total != want {\n        t.Errorf(\"got %f, want %f\", total, want)\n    }\n}\n\n\u002F\u002F 2. 実装する（テストを通す）\nfunc CalculateTotal(prices []float64) float64 {\n    var total float64\n    for _, price := range prices {\n        total += price\n    }\n    return total\n}\n\n\u002F\u002F 3. リファクタリング\n\u002F\u002F テストを壊さずにコードを改善\n```\n\n### 2. テーブル駆動テスト\n\n複数のケースを体系的にテストします。\n\n```go\nfunc TestAdd(t *testing.T) {\n    tests := []struct {\n        name string\n        a, b int\n        want int\n    }{\n        {\"positive numbers\", 2, 3, 5},\n        {\"negative numbers\", -2, -3, -5},\n        {\"mixed signs\", -2, 3, 1},\n        {\"zeros\", 0, 0, 0},\n    }\n\n    for _, tt := range tests {\n        t.Run(tt.name, func(t *testing.T) {\n            got := Add(tt.a, tt.b)\n            if got != tt.want {\n                t.Errorf(\"Add(%d, %d) = %d; want %d\",\n                    tt.a, tt.b, got, tt.want)\n            }\n        })\n    }\n}\n```\n\n### 3. サブテスト\n\nサブテストを使用した論理的なテストの構成。\n\n```go\nfunc TestUser(t *testing.T) {\n    t.Run(\"validation\", func(t *testing.T) {\n        t.Run(\"empty email\", func(t *testing.T) {\n            user := User{Email: \"\"}\n            if err := user.Validate(); err == nil {\n                t.Error(\"expected validation error\")\n            }\n        })\n\n        t.Run(\"valid email\", func(t *testing.T) {\n            user := User{Email: \"test@example.com\"}\n            if err := user.Validate(); err != nil {\n                t.Errorf(\"unexpected error: %v\", err)\n            }\n        })\n    })\n\n    t.Run(\"serialization\", func(t *testing.T) {\n        \u002F\u002F 別のテストグループ\n    })\n}\n```\n\n## テスト構成\n\n### ファイル構成\n\n```text\nmypackage\u002F\n├── user.go\n├── user_test.go          # ユニットテスト\n├── integration_test.go   # 統合テスト\n├── testdata\u002F             # テストフィクスチャ\n│   ├── valid_user.json\n│   └── invalid_user.json\n└── export_test.go        # 内部テスト用の非公開エクスポート\n```\n\n### テストパッケージ\n\n```go\n\u002F\u002F user_test.go - 同じパッケージ（ホワイトボックステスト）\npackage user\n\nfunc TestInternalFunction(t *testing.T) {\n    \u002F\u002F 内部をテストできる\n}\n\n\u002F\u002F user_external_test.go - 外部パッケージ（ブラックボックステスト）\npackage user_test\n\nimport \"myapp\u002Fuser\"\n\nfunc TestPublicAPI(t *testing.T) {\n    \u002F\u002F 公開APIのみをテスト\n}\n```\n\n## アサーションとヘルパー\n\n### 基本的なアサーション\n\n```go\nfunc TestBasicAssertions(t *testing.T) {\n    \u002F\u002F 等価性\n    got := Calculate()\n    want := 42\n    if got != want {\n        t.Errorf(\"got %d, want %d\", got, want)\n    }\n\n    \u002F\u002F エラーチェック\n    _, err := Process()\n    if err != nil {\n        t.Fatalf(\"unexpected error: %v\", err)\n    }\n\n    \u002F\u002F nil チェック\n    result := GetResult()\n    if result == nil {\n        t.Fatal(\"expected non-nil result\")\n    }\n}\n```\n\n### カスタムヘルパー関数\n\n```go\n\u002F\u002F ヘルパーとしてマーク（スタックトレースに表示されない）\nfunc assertEqual(t *testing.T, got, want interface{}) {\n    t.Helper()\n    if got != want {\n        t.Errorf(\"got %v, want %v\", got, want)\n    }\n}\n\nfunc assertNoError(t *testing.T, err error) {\n    t.Helper()\n    if err != nil {\n        t.Fatalf(\"unexpected error: %v\", err)\n    }\n}\n\n\u002F\u002F 使用例\nfunc TestWithHelpers(t *testing.T) {\n    result, err := Process()\n    assertNoError(t, err)\n    assertEqual(t, result.Status, \"success\")\n}\n```\n\n### ディープ等価性チェック\n\n```go\nimport \"reflect\"\n\nfunc assertDeepEqual(t *testing.T, got, want interface{}) {\n    t.Helper()\n    if !reflect.DeepEqual(got, want) {\n        t.Errorf(\"got %+v, want %+v\", got, want)\n    }\n}\n\nfunc TestStructEquality(t *testing.T) {\n    got := User{Name: \"Alice\", Age: 30}\n    want := User{Name: \"Alice\", Age: 30}\n    assertDeepEqual(t, got, want)\n}\n```\n\n## モッキングとスタブ\n\n### インターフェースベースのモック\n\n```go\n\u002F\u002F 本番コード\ntype UserStore interface {\n    GetUser(id string) (*User, error)\n    SaveUser(user *User) error\n}\n\ntype UserService struct {\n    store UserStore\n}\n\n\u002F\u002F テストコード\ntype MockUserStore struct {\n    users map[string]*User\n    err   error\n}\n\nfunc (m *MockUserStore) GetUser(id string) (*User, error) {\n    if m.err != nil {\n        return nil, m.err\n    }\n    return m.users[id], nil\n}\n\nfunc (m *MockUserStore) SaveUser(user *User) error {\n    if m.err != nil {\n        return m.err\n    }\n    m.users[user.ID] = user\n    return nil\n}\n\n\u002F\u002F テスト\nfunc TestUserService(t *testing.T) {\n    mock := &MockUserStore{\n        users: make(map[string]*User),\n    }\n    service := &UserService{store: mock}\n\n    \u002F\u002F サービスをテスト...\n}\n```\n\n### 時間のモック\n\n```go\n\u002F\u002F プロダクションコード - 時間を注入可能にする\ntype TimeProvider interface {\n    Now() time.Time\n}\n\ntype RealTime struct{}\n\nfunc (RealTime) Now() time.Time {\n    return time.Now()\n}\n\ntype Service struct {\n    time TimeProvider\n}\n\n\u002F\u002F テストコード\ntype MockTime struct {\n    current time.Time\n}\n\nfunc (m MockTime) Now() time.Time {\n    return m.current\n}\n\nfunc TestTimeDependent(t *testing.T) {\n    mockTime := MockTime{\n        current: time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC),\n    }\n    service := &Service{time: mockTime}\n\n    \u002F\u002F 固定時間でテスト...\n}\n```\n\n### HTTP クライアントのモック\n\n```go\ntype HTTPClient interface {\n    Do(req *http.Request) (*http.Response, error)\n}\n\ntype MockHTTPClient struct {\n    response *http.Response\n    err      error\n}\n\nfunc (m *MockHTTPClient) Do(req *http.Request) (*http.Response, error) {\n    return m.response, m.err\n}\n\nfunc TestAPICall(t *testing.T) {\n    mockClient := &MockHTTPClient{\n        response: &http.Response{\n            StatusCode: 200,\n            Body:       io.NopCloser(strings.NewReader(`{\"status\":\"ok\"}`)),\n        },\n    }\n\n    api := &APIClient{client: mockClient}\n    \u002F\u002F APIクライアントをテスト...\n}\n```\n\n## HTTPハンドラーのテスト\n\n### httptest の使用\n\n```go\nfunc TestHandler(t *testing.T) {\n    handler := http.HandlerFunc(MyHandler)\n\n    req := httptest.NewRequest(\"GET\", \"\u002Fusers\u002F123\", nil)\n    rec := httptest.NewRecorder()\n\n    handler.ServeHTTP(rec, req)\n\n    \u002F\u002F ステータスコードをチェック\n    if rec.Code != http.StatusOK {\n        t.Errorf(\"got status %d, want %d\", rec.Code, http.StatusOK)\n    }\n\n    \u002F\u002F レスポンスボディをチェック\n    var response map[string]interface{}\n    if err := json.NewDecoder(rec.Body).Decode(&response); err != nil {\n        t.Fatalf(\"failed to decode response: %v\", err)\n    }\n\n    if response[\"id\"] != \"123\" {\n        t.Errorf(\"got id %v, want 123\", response[\"id\"])\n    }\n}\n```\n\n### ミドルウェアのテスト\n\n```go\nfunc TestAuthMiddleware(t *testing.T) {\n    \u002F\u002F ダミーハンドラー\n    nextHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n        w.WriteHeader(http.StatusOK)\n    })\n\n    \u002F\u002F ミドルウェアでラップ\n    handler := AuthMiddleware(nextHandler)\n\n    tests := []struct {\n        name       string\n        token      string\n        wantStatus int\n    }{\n        {\"valid token\", \"valid-token\", http.StatusOK},\n        {\"invalid token\", \"invalid\", http.StatusUnauthorized},\n        {\"no token\", \"\", http.StatusUnauthorized},\n    }\n\n    for _, tt := range tests {\n        t.Run(tt.name, func(t *testing.T) {\n            req := httptest.NewRequest(\"GET\", \"\u002F\", nil)\n            if tt.token != \"\" {\n                req.Header.Set(\"Authorization\", \"Bearer \"+tt.token)\n            }\n            rec := httptest.NewRecorder()\n\n            handler.ServeHTTP(rec, req)\n\n            if rec.Code != tt.wantStatus {\n                t.Errorf(\"got status %d, want %d\", rec.Code, tt.wantStatus)\n            }\n        })\n    }\n}\n```\n\n### テストサーバー\n\n```go\nfunc TestAPIIntegration(t *testing.T) {\n    \u002F\u002F テストサーバーを作成\n    server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n        json.NewEncoder(w).Encode(map[string]string{\n            \"message\": \"hello\",\n        })\n    }))\n    defer server.Close()\n\n    \u002F\u002F 実際のHTTPリクエストを行う\n    resp, err := http.Get(server.URL)\n    if err != nil {\n        t.Fatalf(\"request failed: %v\", err)\n    }\n    defer resp.Body.Close()\n\n    \u002F\u002F レスポンスを検証\n    var result map[string]string\n    json.NewDecoder(resp.Body).Decode(&result)\n\n    if result[\"message\"] != \"hello\" {\n        t.Errorf(\"got %s, want hello\", result[\"message\"])\n    }\n}\n```\n\n## データベーステスト\n\n### トランザクションを使用したテストの分離\n\n```go\nfunc TestUserRepository(t *testing.T) {\n    db := setupTestDB(t)\n    defer db.Close()\n\n    tests := []struct {\n        name string\n        fn   func(*testing.T, *sql.DB)\n    }{\n        {\"create user\", testCreateUser},\n        {\"find user\", testFindUser},\n        {\"update user\", testUpdateUser},\n    }\n\n    for _, tt := range tests {\n        t.Run(tt.name, func(t *testing.T) {\n            tx, err := db.Begin()\n            if err != nil {\n                t.Fatal(err)\n            }\n            defer tx.Rollback() \u002F\u002F テスト後にロールバック\n\n            tt.fn(t, tx)\n        })\n    }\n}\n```\n\n### テストフィクスチャ\n\n```go\nfunc setupTestDB(t *testing.T) *sql.DB {\n    t.Helper()\n\n    db, err := sql.Open(\"postgres\", \"postgres:\u002F\u002Flocalhost\u002Ftest\")\n    if err != nil {\n        t.Fatalf(\"failed to connect: %v\", err)\n    }\n\n    \u002F\u002F スキーマを移行\n    if err := runMigrations(db); err != nil {\n        t.Fatalf(\"migrations failed: %v\", err)\n    }\n\n    return db\n}\n\nfunc seedTestData(t *testing.T, db *sql.DB) {\n    t.Helper()\n\n    fixtures := []string{\n        `INSERT INTO users (id, email) VALUES ('1', 'test@example.com')`,\n        `INSERT INTO posts (id, user_id, title) VALUES ('1', '1', 'Test Post')`,\n    }\n\n    for _, query := range fixtures {\n        if _, err := db.Exec(query); err != nil {\n            t.Fatalf(\"failed to seed data: %v\", err)\n        }\n    }\n}\n```\n\n## ベンチマーク\n\n### 基本的なベンチマーク\n\n```go\nfunc BenchmarkCalculation(b *testing.B) {\n    for i := 0; i \u003C b.N; i++ {\n        Calculate(100)\n    }\n}\n\n\u002F\u002F メモリ割り当てを報告\nfunc BenchmarkWithAllocs(b *testing.B) {\n    b.ReportAllocs()\n    for i := 0; i \u003C b.N; i++ {\n        ProcessData([]byte(\"test data\"))\n    }\n}\n```\n\n### サブベンチマーク\n\n```go\nfunc BenchmarkEncoding(b *testing.B) {\n    data := generateTestData()\n\n    b.Run(\"json\", func(b *testing.B) {\n        b.ReportAllocs()\n        for i := 0; i \u003C b.N; i++ {\n            json.Marshal(data)\n        }\n    })\n\n    b.Run(\"gob\", func(b *testing.B) {\n        b.ReportAllocs()\n        var buf bytes.Buffer\n        enc := gob.NewEncoder(&buf)\n        b.ResetTimer()\n        for i := 0; i \u003C b.N; i++ {\n            enc.Encode(data)\n            buf.Reset()\n        }\n    })\n}\n```\n\n### ベンチマーク比較\n\n```go\n\u002F\u002F 実行: go test -bench=. -benchmem\nfunc BenchmarkStringConcat(b *testing.B) {\n    b.Run(\"operator\", func(b *testing.B) {\n        for i := 0; i \u003C b.N; i++ {\n            _ = \"hello\" + \" \" + \"world\"\n        }\n    })\n\n    b.Run(\"fmt.Sprintf\", func(b *testing.B) {\n        for i := 0; i \u003C b.N; i++ {\n            _ = fmt.Sprintf(\"%s %s\", \"hello\", \"world\")\n        }\n    })\n\n    b.Run(\"strings.Builder\", func(b *testing.B) {\n        for i := 0; i \u003C b.N; i++ {\n            var sb strings.Builder\n            sb.WriteString(\"hello\")\n            sb.WriteString(\" \")\n            sb.WriteString(\"world\")\n            _ = sb.String()\n        }\n    })\n}\n```\n\n## ファジングテスト\n\n### 基本的なファズテスト（Go 1.18+）\n\n```go\nfunc FuzzParseInput(f *testing.F) {\n    \u002F\u002F シードコーパス\n    f.Add(\"hello\")\n    f.Add(\"world\")\n    f.Add(\"123\")\n\n    f.Fuzz(func(t *testing.T, input string) {\n        \u002F\u002F パースがパニックしないことを確認\n        result, err := ParseInput(input)\n\n        \u002F\u002F エラーがあっても、nilでないか一貫性があることを確認\n        if err == nil && result == nil {\n            t.Error(\"got nil result with no error\")\n        }\n    })\n}\n```\n\n### より複雑なファジング\n\n```go\nfunc FuzzJSONParsing(f *testing.F) {\n    f.Add([]byte(`{\"name\":\"test\",\"age\":30}`))\n    f.Add([]byte(`{\"name\":\"\",\"age\":0}`))\n\n    f.Fuzz(func(t *testing.T, data []byte) {\n        var user User\n        err := json.Unmarshal(data, &user)\n\n        \u002F\u002F JSONがデコードされる場合、再度エンコードできるべき\n        if err == nil {\n            _, err := json.Marshal(user)\n            if err != nil {\n                t.Errorf(\"marshal failed after successful unmarshal: %v\", err)\n            }\n        }\n    })\n}\n```\n\n## テストカバレッジ\n\n### カバレッジの実行と表示\n\n```bash\n# カバレッジを実行してHTMLレポートを生成\ngo test -coverprofile=coverage.out .\u002F...\ngo tool cover -html=coverage.out -o coverage.html\n\n# パッケージごとのカバレッジを表示\ngo test -cover .\u002F...\n\n# 詳細なカバレッジ\ngo test -coverprofile=coverage.out -covermode=atomic .\u002F...\n```\n\n### カバレッジのベストプラクティス\n\n```go\n\u002F\u002F Good: テスタブルなコード\nfunc ProcessData(data []byte) (Result, error) {\n    if len(data) == 0 {\n        return Result{}, ErrEmptyData\n    }\n\n    \u002F\u002F 各分岐をテスト可能\n    if isValid(data) {\n        return parseValid(data)\n    }\n    return parseInvalid(data)\n}\n\n\u002F\u002F 対応するテストが全分岐をカバー\nfunc TestProcessData(t *testing.T) {\n    tests := []struct {\n        name    string\n        data    []byte\n        wantErr bool\n    }{\n        {\"empty data\", []byte{}, true},\n        {\"valid data\", []byte(\"valid\"), false},\n        {\"invalid data\", []byte(\"invalid\"), false},\n    }\n    \u002F\u002F ...\n}\n```\n\n## 統合テスト\n\n### ビルドタグの使用\n\n```go\n\u002F\u002Fgo:build integration\n\u002F\u002F +build integration\n\npackage myapp_test\n\nimport \"testing\"\n\nfunc TestDatabaseIntegration(t *testing.T) {\n    \u002F\u002F 実際のDBを必要とするテスト\n}\n```\n\n```bash\n# 統合テストを実行\ngo test -tags=integration .\u002F...\n\n# 統合テストを除外\ngo test .\u002F...\n```\n\n### テストコンテナの使用\n\n```go\nimport \"github.com\u002Ftestcontainers\u002Ftestcontainers-go\"\n\nfunc setupPostgres(t *testing.T) *sql.DB {\n    ctx := context.Background()\n\n    req := testcontainers.ContainerRequest{\n        Image:        \"postgres:15\",\n        ExposedPorts: []string{\"5432\u002Ftcp\"},\n        Env: map[string]string{\n            \"POSTGRES_PASSWORD\": \"test\",\n            \"POSTGRES_DB\":       \"testdb\",\n        },\n    }\n\n    container, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{\n        ContainerRequest: req,\n        Started:          true,\n    })\n    if err != nil {\n        t.Fatal(err)\n    }\n\n    t.Cleanup(func() {\n        container.Terminate(ctx)\n    })\n\n    \u002F\u002F コンテナに接続\n    \u002F\u002F ...\n    return db\n}\n```\n\n## テストの並列化\n\n### 並列テスト\n\n```go\nfunc TestParallel(t *testing.T) {\n    tests := []struct {\n        name string\n        fn   func(*testing.T)\n    }{\n        {\"test1\", testCase1},\n        {\"test2\", testCase2},\n        {\"test3\", testCase3},\n    }\n\n    for _, tt := range tests {\n        tt := tt \u002F\u002F ループ変数をキャプチャ\n        t.Run(tt.name, func(t *testing.T) {\n            t.Parallel() \u002F\u002F このテストを並列実行\n            tt.fn(t)\n        })\n    }\n}\n```\n\n### 並列実行の制御\n\n```go\nfunc TestWithResourceLimit(t *testing.T) {\n    \u002F\u002F 同時に5つのテストのみ\n    sem := make(chan struct{}, 5)\n\n    tests := generateManyTests()\n\n    for _, tt := range tests {\n        tt := tt\n        t.Run(tt.name, func(t *testing.T) {\n            t.Parallel()\n\n            sem \u003C- struct{}{}        \u002F\u002F 獲得\n            defer func() { \u003C-sem }() \u002F\u002F 解放\n\n            tt.fn(t)\n        })\n    }\n}\n```\n\n## Goツール統合\n\n### テストコマンド\n\n```bash\n# 基本テスト\ngo test .\u002F...\ngo test -v .\u002F...                    # 詳細出力\ngo test -run TestSpecific .\u002F...     # 特定のテストを実行\n\n# カバレッジ\ngo test -cover .\u002F...\ngo test -coverprofile=coverage.out .\u002F...\n\n# レースコンディション\ngo test -race .\u002F...\n\n# ベンチマーク\ngo test -bench=. .\u002F...\ngo test -bench=. -benchmem .\u002F...\ngo test -bench=. -cpuprofile=cpu.prof .\u002F...\n\n# ファジング\ngo test -fuzz=FuzzTest\n\n# 統合テスト\ngo test -tags=integration .\u002F...\n\n# JSONフォーマット（CI統合用）\ngo test -json .\u002F...\n```\n\n### テスト設定\n\n```bash\n# テストタイムアウト\ngo test -timeout 30s .\u002F...\n\n# 短時間テスト（長時間テストをスキップ）\ngo test -short .\u002F...\n\n# ビルドキャッシュのクリア\ngo clean -testcache\ngo test .\u002F...\n```\n\n## ベストプラクティス\n\n### DRY（Don't Repeat Yourself）原則\n\n```go\n\u002F\u002F Good: テーブル駆動テストで繰り返しを削減\nfunc TestValidation(t *testing.T) {\n    tests := []struct {\n        input string\n        valid bool\n    }{\n        {\"valid@email.com\", true},\n        {\"invalid-email\", false},\n        {\"\", false},\n    }\n\n    for _, tt := range tests {\n        t.Run(tt.input, func(t *testing.T) {\n            err := Validate(tt.input)\n            if (err == nil) != tt.valid {\n                t.Errorf(\"Validate(%q) error = %v, want valid = %v\",\n                    tt.input, err, tt.valid)\n            }\n        })\n    }\n}\n```\n\n### テストデータの分離\n\n```go\n\u002F\u002F Good: テストデータを testdata\u002F ディレクトリに配置\nfunc TestLoadConfig(t *testing.T) {\n    data, err := os.ReadFile(\"testdata\u002Fconfig.json\")\n    if err != nil {\n        t.Fatal(err)\n    }\n\n    config, err := ParseConfig(data)\n    \u002F\u002F ...\n}\n```\n\n### クリーンアップの使用\n\n```go\nfunc TestWithCleanup(t *testing.T) {\n    \u002F\u002F リソースを設定\n    file, err := os.CreateTemp(\"\", \"test\")\n    if err != nil {\n        t.Fatal(err)\n    }\n\n    \u002F\u002F クリーンアップを登録（deferに似ているが、サブテストで動作）\n    t.Cleanup(func() {\n        os.Remove(file.Name())\n    })\n\n    \u002F\u002F テストを続ける...\n}\n```\n\n### エラーメッセージの明確化\n\n```go\n\u002F\u002F Bad: 不明確なエラー\nif result != expected {\n    t.Error(\"wrong result\")\n}\n\n\u002F\u002F Good: コンテキスト付きエラー\nif result != expected {\n    t.Errorf(\"Calculate(%d) = %d; want %d\", input, result, expected)\n}\n\n\u002F\u002F Better: ヘルパー関数の使用\nassertEqual(t, result, expected, \"Calculate(%d)\", input)\n```\n\n## 避けるべきアンチパターン\n\n```go\n\u002F\u002F Bad: 外部状態に依存\nfunc TestBadDependency(t *testing.T) {\n    result := GetUserFromDatabase(\"123\") \u002F\u002F 実際のDBを使用\n    \u002F\u002F テストが壊れやすく遅い\n}\n\n\u002F\u002F Good: 依存を注入\nfunc TestGoodDependency(t *testing.T) {\n    mockDB := &MockDatabase{\n        users: map[string]User{\"123\": {ID: \"123\"}},\n    }\n    result := GetUser(mockDB, \"123\")\n}\n\n\u002F\u002F Bad: テスト間で状態を共有\nvar sharedCounter int\n\nfunc TestShared1(t *testing.T) {\n    sharedCounter++\n    \u002F\u002F テストの順序に依存\n}\n\n\u002F\u002F Good: 各テストを独立させる\nfunc TestIndependent(t *testing.T) {\n    counter := 0\n    counter++\n    \u002F\u002F 他のテストに影響しない\n}\n\n\u002F\u002F Bad: エラーを無視\nfunc TestIgnoreError(t *testing.T) {\n    result, _ := Process()\n    if result != expected {\n        t.Error(\"wrong result\")\n    }\n}\n\n\u002F\u002F Good: エラーをチェック\nfunc TestCheckError(t *testing.T) {\n    result, err := Process()\n    if err != nil {\n        t.Fatalf(\"Process() error = %v\", err)\n    }\n    if result != expected {\n        t.Errorf(\"got %v, want %v\", result, expected)\n    }\n}\n```\n\n## クイックリファレンス\n\n| コマンド\u002Fパターン | 目的 |\n|--------------|---------|\n| `go test .\u002F...` | すべてのテストを実行 |\n| `go test -v` | 詳細出力 |\n| `go test -cover` | カバレッジレポート |\n| `go test -race` | レースコンディション検出 |\n| `go test -bench=.` | ベンチマークを実行 |\n| `t.Run()` | サブテスト |\n| `t.Helper()` | テストヘルパー関数 |\n| `t.Parallel()` | テストを並列実行 |\n| `t.Cleanup()` | クリーンアップを登録 |\n| `testdata\u002F` | テストフィクスチャ用ディレクトリ |\n| `-short` | 長時間テストをスキップ |\n| `-tags=integration` | ビルドタグでテストを実行 |\n\n**覚えておいてください**: 良いテストは高速で、信頼性があり、保守可能で、明確です。複雑さより明確さを目指してください。\n","# Go テスト\n\nテスト駆動開発(TDD)とGoコードの高品質を保証するための包括的なテスト戦略。\n\n## いつ有効化するか\n\n- 新しいGoコードを書くとき\n- Goコードをレビューするとき\n- 既存のテストを改善するとき\n- テストカバレッジを向上させるとき\n- デバッグとバグ修正時\n\n## 核となる原則\n\n### 1. テスト駆動開発(TDD)ワークフロー\n\n失敗するテストを書き、実装し、リファクタリングするサイクルに従います。\n\n```go\n\u002F\u002F 1. テストを書く（失敗）\nfunc TestCalculateTotal(t *testing.T) {\n    total := CalculateTotal([]float64{10.0, 20.0, 30.0})\n    want := 60.0\n    if total != want {\n        t.Errorf(\"got %f, want %f\", total, want)\n    }\n}\n\n\u002F\u002F 2. 実装する（テストを通す）\nfunc CalculateTotal(prices []float64) float64 {\n    var total float64\n    for _, price := range prices {\n        total += price\n    }\n    return total\n}\n\n\u002F\u002F 3. リファクタリング\n\u002F\u002F テストを壊さずにコードを改善\n```\n\n### 2. テーブル駆動テスト\n\n複数のケースを体系的にテストします。\n\n```go\nfunc TestAdd(t *testing.T) {\n    tests := []struct {\n        name string\n        a, b int\n        want int\n    }{\n        {\"positive numbers\", 2, 3, 5},\n        {\"negative numbers\", -2, -3, -5},\n        {\"mixed signs\", -2, 3, 1},\n        {\"zeros\", 0, 0, 0},\n    }\n\n    for _, tt := range tests {\n        t.Run(tt.name, func(t *testing.T) {\n            got := Add(tt.a, tt.b)\n            if got != tt.want {\n                t.Errorf(\"Add(%d, %d) = %d; want %d\",\n                    tt.a, tt.b, got, tt.want)\n            }\n        })\n    }\n}\n```\n\n### 3. サブテスト\n\nサブテストを使用した論理的なテストの構成。\n\n```go\nfunc TestUser(t *testing.T) {\n    t.Run(\"validation\", func(t *testing.T) {\n        t.Run(\"empty email\", func(t *testing.T) {\n            user := User{Email: \"\"}\n            if err := user.Validate(); err == nil {\n                t.Error(\"expected validation error\")\n            }\n        })\n\n        t.Run(\"valid email\", func(t *testing.T) {\n            user := User{Email: \"test@example.com\"}\n            if err := user.Validate(); err != nil {\n                t.Errorf(\"unexpected error: %v\", err)\n            }\n        })\n    })\n\n    t.Run(\"serialization\", func(t *testing.T) {\n        \u002F\u002F 別のテストグループ\n    })\n}\n```\n\n## テスト構成\n\n### ファイル構成\n\n```text\nmypackage\u002F\n├── user.go\n├── user_test.go          # ユニットテスト\n├── integration_test.go   # 統合テスト\n├── testdata\u002F             # テストフィクスチャ\n│   ├── valid_user.json\n│   └── invalid_user.json\n└── export_test.go        # 内部テスト用の非公開エクスポート\n```\n\n### テストパッケージ\n\n```go\n\u002F\u002F user_test.go - 同じパッケージ（ホワイトボックステスト）\npackage user\n\nfunc TestInternalFunction(t *testing.T) {\n    \u002F\u002F 内部をテストできる\n}\n\n\u002F\u002F user_external_test.go - 外部パッケージ（ブラックボックステスト）\npackage user_test\n\nimport \"myapp\u002Fuser\"\n\nfunc TestPublicAPI(t *testing.T) {\n    \u002F\u002F 公開APIのみをテスト\n}\n```\n\n## アサーションとヘルパー\n\n### 基本的なアサーション\n\n```go\nfunc TestBasicAssertions(t *testing.T) {\n    \u002F\u002F 等価性\n    got := Calculate()\n    want := 42\n    if got != want {\n        t.Errorf(\"got %d, want %d\", got, want)\n    }\n\n    \u002F\u002F エラーチェック\n    _, err := Process()\n    if err != nil {\n        t.Fatalf(\"unexpected error: %v\", err)\n    }\n\n    \u002F\u002F nil チェック\n    result := GetResult()\n    if result == nil {\n        t.Fatal(\"expected non-nil result\")\n    }\n}\n```\n\n### カスタムヘルパー関数\n\n```go\n\u002F\u002F ヘルパーとしてマーク（スタックトレースに表示されない）\nfunc assertEqual(t *testing.T, got, want interface{}) {\n    t.Helper()\n    if got != want {\n        t.Errorf(\"got %v, want %v\", got, want)\n    }\n}\n\nfunc assertNoError(t *testing.T, err error) {\n    t.Helper()\n    if err != nil {\n        t.Fatalf(\"unexpected error: %v\", err)\n    }\n}\n\n\u002F\u002F 使用例\nfunc TestWithHelpers(t *testing.T) {\n    result, err := Process()\n    assertNoError(t, err)\n    assertEqual(t, result.Status, \"success\")\n}\n```\n\n### ディープ等価性チェック\n\n```go\nimport \"reflect\"\n\nfunc assertDeepEqual(t *testing.T, got, want interface{}) {\n    t.Helper()\n    if !reflect.DeepEqual(got, want) {\n        t.Errorf(\"got %+v, want %+v\", got, want)\n    }\n}\n\nfunc TestStructEquality(t *testing.T) {\n    got := User{Name: \"Alice\", Age: 30}\n    want := User{Name: \"Alice\", Age: 30}\n    assertDeepEqual(t, got, want)\n}\n```\n\n## モッキングとスタブ\n\n### インターフェースベースのモック\n\n```go\n\u002F\u002F 本番コード\ntype UserStore interface {\n    GetUser(id string) (*User, error)\n    SaveUser(user *User) error\n}\n\ntype UserService struct {\n    store UserStore\n}\n\n\u002F\u002F テストコード\ntype MockUserStore struct {\n    users map[string]*User\n    err   error\n}\n\nfunc (m *MockUserStore) GetUser(id string) (*User, error) {\n    if m.err != nil {\n        return nil, m.err\n    }\n    return m.users[id], nil\n}\n\nfunc (m *MockUserStore) SaveUser(user *User) error {\n    if m.err != nil {\n        return m.err\n    }\n    m.users[user.ID] = user\n    return nil\n}\n\n\u002F\u002F テスト\nfunc TestUserService(t *testing.T) {\n    mock := &MockUserStore{\n        users: make(map[string]*User),\n    }\n    service := &UserService{store: mock}\n\n    \u002F\u002F サービスをテスト...\n}\n```\n\n### 時間のモック\n\n```go\n\u002F\u002F プロダクションコード - 時間を注入可能にする\ntype TimeProvider interface {\n    Now() time.Time\n}\n\ntype RealTime struct{}\n\nfunc (RealTime) Now() time.Time {\n    return time.Now()\n}\n\ntype Service struct {\n    time TimeProvider\n}\n\n\u002F\u002F テストコード\ntype MockTime struct {\n    current time.Time\n}\n\nfunc (m MockTime) Now() time.Time {\n    return m.current\n}\n\nfunc TestTimeDependent(t *testing.T) {\n    mockTime := MockTime{\n        current: time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC),\n    }\n    service := &Service{time: mockTime}\n\n    \u002F\u002F 固定時間でテスト...\n}\n```\n\n### HTTP クライアントのモック\n\n```go\ntype HTTPClient interface {\n    Do(req *http.Request) (*http.Response, error)\n}\n\ntype MockHTTPClient struct {\n    response *http.Response\n    err      error\n}\n\nfunc (m *MockHTTPClient) Do(req *http.Request) (*http.Response, error) {\n    return m.response, m.err\n}\n\nfunc TestAPICall(t *testing.T) {\n    mockClient := &MockHTTPClient{\n        response: &http.Response{\n            StatusCode: 200,\n            Body:       io.NopCloser(strings.NewReader(`{\"status\":\"ok\"}`)),\n        },\n    }\n\n    api := &APIClient{client: mockClient}\n    \u002F\u002F APIクライアントをテスト...\n}\n```\n\n## HTTPハンドラーのテスト\n\n### httptest の使用\n\n```go\nfunc TestHandler(t *testing.T) {\n    handler := http.HandlerFunc(MyHandler)\n\n    req := httptest.NewRequest(\"GET\", \"\u002Fusers\u002F123\", nil)\n    rec := httptest.NewRecorder()\n\n    handler.ServeHTTP(rec, req)\n\n    \u002F\u002F ステータスコードをチェック\n    if rec.Code != http.StatusOK {\n        t.Errorf(\"got status %d, want %d\", rec.Code, http.StatusOK)\n    }\n\n    \u002F\u002F レスポンスボディをチェック\n    var response map[string]interface{}\n    if err := json.NewDecoder(rec.Body).Decode(&response); err != nil {\n        t.Fatalf(\"failed to decode response: %v\", err)\n    }\n\n    if response[\"id\"] != \"123\" {\n        t.Errorf(\"got id %v, want 123\", response[\"id\"])\n    }\n}\n```\n\n### ミドルウェアのテスト\n\n```go\nfunc TestAuthMiddleware(t *testing.T) {\n    \u002F\u002F ダミーハンドラー\n    nextHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n        w.WriteHeader(http.StatusOK)\n    })\n\n    \u002F\u002F ミドルウェアでラップ\n    handler := AuthMiddleware(nextHandler)\n\n    tests := []struct {\n        name       string\n        token      string\n        wantStatus int\n    }{\n        {\"valid token\", \"valid-token\", http.StatusOK},\n        {\"invalid token\", \"invalid\", http.StatusUnauthorized},\n        {\"no token\", \"\", http.StatusUnauthorized},\n    }\n\n    for _, tt := range tests {\n        t.Run(tt.name, func(t *testing.T) {\n            req := httptest.NewRequest(\"GET\", \"\u002F\", nil)\n            if tt.token != \"\" {\n                req.Header.Set(\"Authorization\", \"Bearer \"+tt.token)\n            }\n            rec := httptest.NewRecorder()\n\n            handler.ServeHTTP(rec, req)\n\n            if rec.Code != tt.wantStatus {\n                t.Errorf(\"got status %d, want %d\", rec.Code, tt.wantStatus)\n            }\n        })\n    }\n}\n```\n\n### テストサーバー\n\n```go\nfunc TestAPIIntegration(t *testing.T) {\n    \u002F\u002F テストサーバーを作成\n    server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n        json.NewEncoder(w).Encode(map[string]string{\n            \"message\": \"hello\",\n        })\n    }))\n    defer server.Close()\n\n    \u002F\u002F 実際のHTTPリクエストを行う\n    resp, err := http.Get(server.URL)\n    if err != nil {\n        t.Fatalf(\"request failed: %v\", err)\n    }\n    defer resp.Body.Close()\n\n    \u002F\u002F レスポンスを検証\n    var result map[string]string\n    json.NewDecoder(resp.Body).Decode(&result)\n\n    if result[\"message\"] != \"hello\" {\n        t.Errorf(\"got %s, want hello\", result[\"message\"])\n    }\n}\n```\n\n## データベーステスト\n\n### トランザクションを使用したテストの分離\n\n```go\nfunc TestUserRepository(t *testing.T) {\n    db := setupTestDB(t)\n    defer db.Close()\n\n    tests := []struct {\n        name string\n        fn   func(*testing.T, *sql.DB)\n    }{\n        {\"create user\", testCreateUser},\n        {\"find user\", testFindUser},\n        {\"update user\", testUpdateUser},\n    }\n\n    for _, tt := range tests {\n        t.Run(tt.name, func(t *testing.T) {\n            tx, err := db.Begin()\n            if err != nil {\n                t.Fatal(err)\n            }\n            defer tx.Rollback() \u002F\u002F テスト後にロールバック\n\n            tt.fn(t, tx)\n        })\n    }\n}\n```\n\n### テストフィクスチャ\n\n```go\nfunc setupTestDB(t *testing.T) *sql.DB {\n    t.Helper()\n\n    db, err := sql.Open(\"postgres\", \"postgres:\u002F\u002Flocalhost\u002Ftest\")\n    if err != nil {\n        t.Fatalf(\"failed to connect: %v\", err)\n    }\n\n    \u002F\u002F スキーマを移行\n    if err := runMigrations(db); err != nil {\n        t.Fatalf(\"migrations failed: %v\", err)\n    }\n\n    return db\n}\n\nfunc seedTestData(t *testing.T, db *sql.DB) {\n    t.Helper()\n\n    fixtures := []string{\n        `INSERT INTO users (id, email) VALUES ('1', 'test@example.com')`,\n        `INSERT INTO posts (id, user_id, title) VALUES ('1', '1', 'Test Post')`,\n    }\n\n    for _, query := range fixtures {\n        if _, err := db.Exec(query); err != nil {\n            t.Fatalf(\"failed to seed data: %v\", err)\n        }\n    }\n}\n```\n\n## ベンチマーク\n\n### 基本的なベンチマーク\n\n```go\nfunc BenchmarkCalculation(b *testing.B) {\n    for i := 0; i \u003C b.N; i++ {\n        Calculate(100)\n    }\n}\n\n\u002F\u002F メモリ割り当てを報告\nfunc BenchmarkWithAllocs(b *testing.B) {\n    b.ReportAllocs()\n    for i := 0; i \u003C b.N; i++ {\n        ProcessData([]byte(\"test data\"))\n    }\n}\n```\n\n### サブベンチマーク\n\n```go\nfunc BenchmarkEncoding(b *testing.B) {\n    data := generateTestData()\n\n    b.Run(\"json\", func(b *testing.B) {\n        b.ReportAllocs()\n        for i := 0; i \u003C b.N; i++ {\n            json.Marshal(data)\n        }\n    })\n\n    b.Run(\"gob\", func(b *testing.B) {\n        b.ReportAllocs()\n        var buf bytes.Buffer\n        enc := gob.NewEncoder(&buf)\n        b.ResetTimer()\n        for i := 0; i \u003C b.N; i++ {\n            enc.Encode(data)\n            buf.Reset()\n        }\n    })\n}\n```\n\n### ベンチマーク比較\n\n```go\n\u002F\u002F 実行: go test -bench=. -benchmem\nfunc BenchmarkStringConcat(b *testing.B) {\n    b.Run(\"operator\", func(b *testing.B) {\n        for i := 0; i \u003C b.N; i++ {\n            _ = \"hello\" + \" \" + \"world\"\n        }\n    })\n\n    b.Run(\"fmt.Sprintf\", func(b *testing.B) {\n        for i := 0; i \u003C b.N; i++ {\n            _ = fmt.Sprintf(\"%s %s\", \"hello\", \"world\")\n        }\n    })\n\n    b.Run(\"strings.Builder\", func(b *testing.B) {\n        for i := 0; i \u003C b.N; i++ {\n            var sb strings.Builder\n            sb.WriteString(\"hello\")\n            sb.WriteString(\" \")\n            sb.WriteString(\"world\")\n            _ = sb.String()\n        }\n    })\n}\n```\n\n## ファジングテスト\n\n### 基本的なファズテスト（Go 1.18+）\n\n```go\nfunc FuzzParseInput(f *testing.F) {\n    \u002F\u002F シードコーパス\n    f.Add(\"hello\")\n    f.Add(\"world\")\n    f.Add(\"123\")\n\n    f.Fuzz(func(t *testing.T, input string) {\n        \u002F\u002F パースがパニックしないことを確認\n        result, err := ParseInput(input)\n\n        \u002F\u002F エラーがあっても、nilでないか一貫性があることを確認\n        if err == nil && result == nil {\n            t.Error(\"got nil result with no error\")\n        }\n    })\n}\n```\n\n### より複雑なファジング\n\n```go\nfunc FuzzJSONParsing(f *testing.F) {\n    f.Add([]byte(`{\"name\":\"test\",\"age\":30}`))\n    f.Add([]byte(`{\"name\":\"\",\"age\":0}`))\n\n    f.Fuzz(func(t *testing.T, data []byte) {\n        var user User\n        err := json.Unmarshal(data, &user)\n\n        \u002F\u002F JSONがデコードされる場合、再度エンコードできるべき\n        if err == nil {\n            _, err := json.Marshal(user)\n            if err != nil {\n                t.Errorf(\"marshal failed after successful unmarshal: %v\", err)\n            }\n        }\n    })\n}\n```\n\n## テストカバレッジ\n\n### カバレッジの実行と表示\n\n```bash\n# カバレッジを実行してHTMLレポートを生成\ngo test -coverprofile=coverage.out .\u002F...\ngo tool cover -html=coverage.out -o coverage.html\n\n# パッケージごとのカバレッジを表示\ngo test -cover .\u002F...\n\n# 詳細なカバレッジ\ngo test -coverprofile=coverage.out -covermode=atomic .\u002F...\n```\n\n### カバレッジのベストプラクティス\n\n```go\n\u002F\u002F Good: テスタブルなコード\nfunc ProcessData(data []byte) (Result, error) {\n    if len(data) == 0 {\n        return Result{}, ErrEmptyData\n    }\n\n    \u002F\u002F 各分岐をテスト可能\n    if isValid(data) {\n        return parseValid(data)\n    }\n    return parseInvalid(data)\n}\n\n\u002F\u002F 対応するテストが全分岐をカバー\nfunc TestProcessData(t *testing.T) {\n    tests := []struct {\n        name    string\n        data    []byte\n        wantErr bool\n    }{\n        {\"empty data\", []byte{}, true},\n        {\"valid data\", []byte(\"valid\"), false},\n        {\"invalid data\", []byte(\"invalid\"), false},\n    }\n    \u002F\u002F ...\n}\n```\n\n## 統合テスト\n\n### ビルドタグの使用\n\n```go\n\u002F\u002Fgo:build integration\n\u002F\u002F +build integration\n\npackage myapp_test\n\nimport \"testing\"\n\nfunc TestDatabaseIntegration(t *testing.T) {\n    \u002F\u002F 実際のDBを必要とするテスト\n}\n```\n\n```bash\n# 統合テストを実行\ngo test -tags=integration .\u002F...\n\n# 統合テストを除外\ngo test .\u002F...\n```\n\n### テストコンテナの使用\n\n```go\nimport \"github.com\u002Ftestcontainers\u002Ftestcontainers-go\"\n\nfunc setupPostgres(t *testing.T) *sql.DB {\n    ctx := context.Background()\n\n    req := testcontainers.ContainerRequest{\n        Image:        \"postgres:15\",\n        ExposedPorts: []string{\"5432\u002Ftcp\"},\n        Env: map[string]string{\n            \"POSTGRES_PASSWORD\": \"test\",\n            \"POSTGRES_DB\":       \"testdb\",\n        },\n    }\n\n    container, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{\n        ContainerRequest: req,\n        Started:          true,\n    })\n    if err != nil {\n        t.Fatal(err)\n    }\n\n    t.Cleanup(func() {\n        container.Terminate(ctx)\n    })\n\n    \u002F\u002F コンテナに接続\n    \u002F\u002F ...\n    return db\n}\n```\n\n## テストの並列化\n\n### 並列テスト\n\n```go\nfunc TestParallel(t *testing.T) {\n    tests := []struct {\n        name string\n        fn   func(*testing.T)\n    }{\n        {\"test1\", testCase1},\n        {\"test2\", testCase2},\n        {\"test3\", testCase3},\n    }\n\n    for _, tt := range tests {\n        tt := tt \u002F\u002F ループ変数をキャプチャ\n        t.Run(tt.name, func(t *testing.T) {\n            t.Parallel() \u002F\u002F このテストを並列実行\n            tt.fn(t)\n        })\n    }\n}\n```\n\n### 並列実行の制御\n\n```go\nfunc TestWithResourceLimit(t *testing.T) {\n    \u002F\u002F 同時に5つのテストのみ\n    sem := make(chan struct{}, 5)\n\n    tests := generateManyTests()\n\n    for _, tt := range tests {\n        tt := tt\n        t.Run(tt.name, func(t *testing.T) {\n            t.Parallel()\n\n            sem \u003C- struct{}{}        \u002F\u002F 獲得\n            defer func() { \u003C-sem }() \u002F\u002F 解放\n\n            tt.fn(t)\n        })\n    }\n}\n```\n\n## Goツール統合\n\n### テストコマンド\n\n```bash\n# 基本テスト\ngo test .\u002F...\ngo test -v .\u002F...                    # 詳細出力\ngo test -run TestSpecific .\u002F...     # 特定のテストを実行\n\n# カバレッジ\ngo test -cover .\u002F...\ngo test -coverprofile=coverage.out .\u002F...\n\n# レースコンディション\ngo test -race .\u002F...\n\n# ベンチマーク\ngo test -bench=. .\u002F...\ngo test -bench=. -benchmem .\u002F...\ngo test -bench=. -cpuprofile=cpu.prof .\u002F...\n\n# ファジング\ngo test -fuzz=FuzzTest\n\n# 統合テスト\ngo test -tags=integration .\u002F...\n\n# JSONフォーマット（CI統合用）\ngo test -json .\u002F...\n```\n\n### テスト設定\n\n```bash\n# テストタイムアウト\ngo test -timeout 30s .\u002F...\n\n# 短時間テスト（長時間テストをスキップ）\ngo test -short .\u002F...\n\n# ビルドキャッシュのクリア\ngo clean -testcache\ngo test .\u002F...\n```\n\n## ベストプラクティス\n\n### DRY（Don't Repeat Yourself）原則\n\n```go\n\u002F\u002F Good: テーブル駆動テストで繰り返しを削減\nfunc TestValidation(t *testing.T) {\n    tests := []struct {\n        input string\n        valid bool\n    }{\n        {\"valid@email.com\", true},\n        {\"invalid-email\", false},\n        {\"\", false},\n    }\n\n    for _, tt := range tests {\n        t.Run(tt.input, func(t *testing.T) {\n            err := Validate(tt.input)\n            if (err == nil) != tt.valid {\n                t.Errorf(\"Validate(%q) error = %v, want valid = %v\",\n                    tt.input, err, tt.valid)\n            }\n        })\n    }\n}\n```\n\n### テストデータの分離\n\n```go\n\u002F\u002F Good: テストデータを testdata\u002F ディレクトリに配置\nfunc TestLoadConfig(t *testing.T) {\n    data, err := os.ReadFile(\"testdata\u002Fconfig.json\")\n    if err != nil {\n        t.Fatal(err)\n    }\n\n    config, err := ParseConfig(data)\n    \u002F\u002F ...\n}\n```\n\n### クリーンアップの使用\n\n```go\nfunc TestWithCleanup(t *testing.T) {\n    \u002F\u002F リソースを設定\n    file, err := os.CreateTemp(\"\", \"test\")\n    if err != nil {\n        t.Fatal(err)\n    }\n\n    \u002F\u002F クリーンアップを登録（deferに似ているが、サブテストで動作）\n    t.Cleanup(func() {\n        os.Remove(file.Name())\n    })\n\n    \u002F\u002F テストを続ける...\n}\n```\n\n### エラーメッセージの明確化\n\n```go\n\u002F\u002F Bad: 不明確なエラー\nif result != expected {\n    t.Error(\"wrong result\")\n}\n\n\u002F\u002F Good: コンテキスト付きエラー\nif result != expected {\n    t.Errorf(\"Calculate(%d) = %d; want %d\", input, result, expected)\n}\n\n\u002F\u002F Better: ヘルパー関数の使用\nassertEqual(t, result, expected, \"Calculate(%d)\", input)\n```\n\n## 避けるべきアンチパターン\n\n```go\n\u002F\u002F Bad: 外部状態に依存\nfunc TestBadDependency(t *testing.T) {\n    result := GetUserFromDatabase(\"123\") \u002F\u002F 実際のDBを使用\n    \u002F\u002F テストが壊れやすく遅い\n}\n\n\u002F\u002F Good: 依存を注入\nfunc TestGoodDependency(t *testing.T) {\n    mockDB := &MockDatabase{\n        users: map[string]User{\"123\": {ID: \"123\"}},\n    }\n    result := GetUser(mockDB, \"123\")\n}\n\n\u002F\u002F Bad: テスト間で状態を共有\nvar sharedCounter int\n\nfunc TestShared1(t *testing.T) {\n    sharedCounter++\n    \u002F\u002F テストの順序に依存\n}\n\n\u002F\u002F Good: 各テストを独立させる\nfunc TestIndependent(t *testing.T) {\n    counter := 0\n    counter++\n    \u002F\u002F 他のテストに影響しない\n}\n\n\u002F\u002F Bad: エラーを無視\nfunc TestIgnoreError(t *testing.T) {\n    result, _ := Process()\n    if result != expected {\n        t.Error(\"wrong result\")\n    }\n}\n\n\u002F\u002F Good: エラーをチェック\nfunc TestCheckError(t *testing.T) {\n    result, err := Process()\n    if err != nil {\n        t.Fatalf(\"Process() error = %v\", err)\n    }\n    if result != expected {\n        t.Errorf(\"got %v, want %v\", result, expected)\n    }\n}\n```\n\n## クイックリファレンス\n\n| コマンド\u002Fパターン | 目的 |\n|--------------|---------|\n| `go test .\u002F...` | すべてのテストを実行 |\n| `go test -v` | 詳細出力 |\n| `go test -cover` | カバレッジレポート |\n| `go test -race` | レースコンディション検出 |\n| `go test -bench=.` | ベンチマークを実行 |\n| `t.Run()` | サブテスト |\n| `t.Helper()` | テストヘルパー関数 |\n| `t.Parallel()` | テストを並列実行 |\n| `t.Cleanup()` | クリーンアップを登録 |\n| `testdata\u002F` | テストフィクスチャ用ディレクトリ |\n| `-short` | 長時間テストをスキップ |\n| `-tags=integration` | ビルドタグでテストを実行 |\n\n**覚えておいてください**: 良いテストは高速で、信頼性があり、保守可能で、明確です。複雑さより明確さを目指してください。\n",{"name":5,"description":7},"master","d6ca01da0f24a3b0e26e4a8b7b66cbd25d429f5d","everything-claude-code\u002Fdocs\u002Fja-JP\u002Fskills\u002Fgolang-testing",0,"https:\u002F\u002Fgithub.com\u002FSriramGandhiS\u002FSkills","https:\u002F\u002Fgithub.com\u002FSriramGandhiS","https:\u002F\u002Fsriram.website\u002F","Curious guy who keeps tinkering until something works","2026-05-20 16:21:34",{"source":8,"skillName":5,"commands":34,"prompt":44,"zipAvailable":45},[35,38,41],{"tool":36,"command":37},"npx","npx skills add SriramGandhiS\u002FSkills --skill golang-testing",{"tool":39,"command":40},"bunx","bunx skills add SriramGandhiS\u002FSkills --skill golang-testing",{"tool":42,"command":43},"pnpm","pnpm dlx skills add SriramGandhiS\u002FSkills --skill golang-testing","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FSriramGandhiS\u002FSkills\u002Fblob\u002Fmaster\u002Feverything-claude-code\u002Fdocs\u002Fja-JP\u002Fskills\u002Fgolang-testing\u002FSKILL.md",true,[],[48,56,61,67,74,81],{"skillNo":49,"name":50,"nameZh":6,"description":51,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":52,"categories":53,"keywords":54,"publishedAt":55},"01M732609EPJWV13PVTX3GT4TM","webgpu-threejs-tsl","Comprehensive guide for developing WebGPU-enabled Three.js applications using TSL (Three.js Shading Language). Covers WebGPU renderer setup, TSL syntax and node materials, compute shaders, post-processing effects, and WGSL integration. Use this skill when working with Three.js WebGPU, TSL shaders, node materials, or GPU compute in Three.js.","https:\u002F\u002Fgithub.com\u002FSriramGandhiS\u002FSkills\u002Fblob\u002Fmaster\u002Fwebgpu-threejs-tsl\u002Fskills\u002Fwebgpu-threejs-tsl\u002FSKILL.md",[],[],"2026-11-11 15:11:14",{"skillNo":57,"name":50,"nameZh":6,"description":51,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":58,"categories":59,"keywords":60,"publishedAt":55},"01M7325XM47AGWB6K6C4VXKE6B","https:\u002F\u002Fgithub.com\u002FSriramGandhiS\u002FSkills\u002Fblob\u002Fmaster\u002Fwebgpu-threejs-tsl\u002FSKILL.md",[],[],{"skillNo":62,"name":63,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":64,"categories":65,"keywords":66,"publishedAt":55},"01M7325WP6DES69JKC840VMFEP","verification-loop","https:\u002F\u002Fgithub.com\u002FSriramGandhiS\u002FSkills\u002Fblob\u002Fmaster\u002Fweb-assets\u002Fdocs\u002Fzh-TW\u002Fskills\u002Fverification-loop\u002FSKILL.md",[],[],{"skillNo":68,"name":69,"nameZh":6,"description":70,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":71,"categories":72,"keywords":73,"publishedAt":55},"01M7325TFQF1DZTQ6J3WGQQ1VR","tdd-workflow","Use this skill when writing new features, fixing bugs, or refactoring code. Enforces test-driven development with 80%+ coverage including unit, integration, and E2E tests.","https:\u002F\u002Fgithub.com\u002FSriramGandhiS\u002FSkills\u002Fblob\u002Fmaster\u002Fweb-assets\u002Fdocs\u002Fzh-TW\u002Fskills\u002Ftdd-workflow\u002FSKILL.md",[],[],{"skillNo":75,"name":76,"nameZh":6,"description":77,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":78,"categories":79,"keywords":80,"publishedAt":55},"01M7325RGV9AY9PK92D2V8KKPW","strategic-compact","Suggests manual context compaction at logical intervals to preserve context through task phases rather than arbitrary auto-compaction.","https:\u002F\u002Fgithub.com\u002FSriramGandhiS\u002FSkills\u002Fblob\u002Fmaster\u002Fweb-assets\u002Fdocs\u002Fzh-TW\u002Fskills\u002Fstrategic-compact\u002FSKILL.md",[],[],{"skillNo":82,"name":83,"nameZh":6,"description":84,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":85,"categories":86,"keywords":87,"publishedAt":55},"01M7325MZC28SE86E7NMCNEFS4","security-review","Use this skill when adding authentication, handling user input, working with secrets, creating API endpoints, or implementing payment\u002Fsensitive features. Provides comprehensive security checklist and patterns.","https:\u002F\u002Fgithub.com\u002FSriramGandhiS\u002FSkills\u002Fblob\u002Fmaster\u002Fweb-assets\u002Fdocs\u002Fzh-TW\u002Fskills\u002Fsecurity-review\u002FSKILL.md",[],[]]