[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6D7WQZXJREVTJC0DF3JP6CQ":3,"skill-same:01M6D7WQZXJREVTJC0DF3JP6CQ":50},{"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":22,"linkOnly":23,"markdownContent":24,"markdownBody":25,"frontMatter":26,"refName":27,"commitSha":28,"skillDirectory":29,"forksCount":30,"repositoryHtmlUrl":31,"repositoryHomepageUrl":6,"ownerHtmlUrl":32,"ownerBlogUrl":33,"ownerDescription":34,"updatedAt":35,"install":36,"resources":49},"01M6D7WQZXJREVTJC0DF3JP6CQ","tdd-workflow",null,"新機能の作成、バグ修正、コードのリファクタリング時にこのスキルを使用します。ユニット、統合、E2Eテストを含む80%以上のカバレッジでテスト駆動開発を強制します。","oabdelmaksoud\u002FSuperClaw","oabdelmaksoud","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F50699149?v=4","01M6D5CVVN778ZCDP1WHS816SP","Omar Abdelmaksoud","01M6D5CW1RHNSKCJR85GJACBFT",2,"MIT","https:\u002F\u002Fgithub.com\u002Foabdelmaksoud\u002FSuperClaw\u002Fblob\u002Fmain\u002Fupstream-sync\u002Fwork\u002Fecc\u002Fdocs\u002Fja-JP\u002Fskills\u002Ftdd-workflow\u002FSKILL.md",[],[19,20,21],"tdd","workflow","tdd workflow","2026-11-10 10:12:30",false,"---\nname: tdd-workflow\ndescription: 新機能の作成、バグ修正、コードのリファクタリング時にこのスキルを使用します。ユニット、統合、E2Eテストを含む80%以上のカバレッジでテスト駆動開発を強制します。\n---\n\n# テスト駆動開発ワークフロー\n\nこのスキルは、すべてのコード開発が包括的なテストカバレッジを備えたTDDの原則に従うことを保証します。\n\n## 有効化するタイミング\n\n- 新機能や機能の作成\n- バグや問題の修正\n- 既存コードのリファクタリング\n- APIエンドポイントの追加\n- 新しいコンポーネントの作成\n\n## コア原則\n\n### 1. コードの前にテスト\n常にテストを最初に書き、次にテストに合格するコードを実装します。\n\n### 2. カバレッジ要件\n- 最低80%のカバレッジ（ユニット + 統合 + E2E）\n- すべてのエッジケースをカバー\n- エラーシナリオのテスト\n- 境界条件の検証\n\n### 3. テストタイプ\n\n#### ユニットテスト\n- 個々の関数とユーティリティ\n- コンポーネントロジック\n- 純粋関数\n- ヘルパーとユーティリティ\n\n#### 統合テスト\n- APIエンドポイント\n- データベース操作\n- サービス間相互作用\n- 外部API呼び出し\n\n#### E2Eテスト (Playwright)\n- クリティカルなユーザーフロー\n- 完全なワークフロー\n- ブラウザ自動化\n- UI相互作用\n\n## TDDワークフローステップ\n\n### ステップ1：ユーザージャーニーを書く\n```\n[役割]として、[行動]をしたい、それによって[利益]を得られるようにするため\n\n例：\nユーザーとして、セマンティックに市場を検索したい、\nそれによって正確なキーワードなしでも関連する市場を見つけられるようにするため。\n```\n\n### ステップ2：テストケースを生成\n各ユーザージャーニーについて、包括的なテストケースを作成：\n\n```typescript\ndescribe('Semantic Search', () => {\n  it('returns relevant markets for query', async () => {\n    \u002F\u002F テスト実装\n  })\n\n  it('handles empty query gracefully', async () => {\n    \u002F\u002F エッジケースのテスト\n  })\n\n  it('falls back to substring search when Redis unavailable', async () => {\n    \u002F\u002F フォールバック動作のテスト\n  })\n\n  it('sorts results by similarity score', async () => {\n    \u002F\u002F ソートロジックのテスト\n  })\n})\n```\n\n### ステップ3：テストを実行（失敗するはず）\n```bash\nnpm test\n# テストは失敗するはず - まだ実装していない\n```\n\n### ステップ4：コードを実装\nテストに合格する最小限のコードを書く：\n\n```typescript\n\u002F\u002F テストにガイドされた実装\nexport async function searchMarkets(query: string) {\n  \u002F\u002F 実装はここ\n}\n```\n\n### ステップ5：テストを再実行\n```bash\nnpm test\n# テストは今度は成功するはず\n```\n\n### ステップ6：リファクタリング\nテストをグリーンに保ちながらコード品質を向上：\n- 重複を削除\n- 命名を改善\n- パフォーマンスを最適化\n- 可読性を向上\n\n### ステップ7：カバレッジを確認\n```bash\nnpm run test:coverage\n# 80%以上のカバレッジを達成したことを確認\n```\n\n## テストパターン\n\n### ユニットテストパターン (Jest\u002FVitest)\n```typescript\nimport { render, screen, fireEvent } from '@testing-library\u002Freact'\nimport { Button } from '.\u002FButton'\n\ndescribe('Button Component', () => {\n  it('renders with correct text', () => {\n    render(\u003CButton>Click me\u003C\u002FButton>)\n    expect(screen.getByText('Click me')).toBeInTheDocument()\n  })\n\n  it('calls onClick when clicked', () => {\n    const handleClick = jest.fn()\n    render(\u003CButton onClick={handleClick}>Click\u003C\u002FButton>)\n\n    fireEvent.click(screen.getByRole('button'))\n\n    expect(handleClick).toHaveBeenCalledTimes(1)\n  })\n\n  it('is disabled when disabled prop is true', () => {\n    render(\u003CButton disabled>Click\u003C\u002FButton>)\n    expect(screen.getByRole('button')).toBeDisabled()\n  })\n})\n```\n\n### API統合テストパターン\n```typescript\nimport { NextRequest } from 'next\u002Fserver'\nimport { GET } from '.\u002Froute'\n\ndescribe('GET \u002Fapi\u002Fmarkets', () => {\n  it('returns markets successfully', async () => {\n    const request = new NextRequest('http:\u002F\u002Flocalhost\u002Fapi\u002Fmarkets')\n    const response = await GET(request)\n    const data = await response.json()\n\n    expect(response.status).toBe(200)\n    expect(data.success).toBe(true)\n    expect(Array.isArray(data.data)).toBe(true)\n  })\n\n  it('validates query parameters', async () => {\n    const request = new NextRequest('http:\u002F\u002Flocalhost\u002Fapi\u002Fmarkets?limit=invalid')\n    const response = await GET(request)\n\n    expect(response.status).toBe(400)\n  })\n\n  it('handles database errors gracefully', async () => {\n    \u002F\u002F データベース障害をモック\n    const request = new NextRequest('http:\u002F\u002Flocalhost\u002Fapi\u002Fmarkets')\n    \u002F\u002F エラー処理のテスト\n  })\n})\n```\n\n### E2Eテストパターン (Playwright)\n```typescript\nimport { test, expect } from '@playwright\u002Ftest'\n\ntest('user can search and filter markets', async ({ page }) => {\n  \u002F\u002F 市場ページに移動\n  await page.goto('\u002F')\n  await page.click('a[href=\"\u002Fmarkets\"]')\n\n  \u002F\u002F ページが読み込まれたことを確認\n  await expect(page.locator('h1')).toContainText('Markets')\n\n  \u002F\u002F 市場を検索\n  await page.fill('input[placeholder=\"Search markets\"]', 'election')\n\n  \u002F\u002F デバウンスと結果を待つ\n  await page.waitForTimeout(600)\n\n  \u002F\u002F 検索結果が表示されることを確認\n  const results = page.locator('[data-testid=\"market-card\"]')\n  await expect(results).toHaveCount(5, { timeout: 5000 })\n\n  \u002F\u002F 結果に検索語が含まれることを確認\n  const firstResult = results.first()\n  await expect(firstResult).toContainText('election', { ignoreCase: true })\n\n  \u002F\u002F ステータスでフィルタリング\n  await page.click('button:has-text(\"Active\")')\n\n  \u002F\u002F フィルタリングされた結果を確認\n  await expect(results).toHaveCount(3)\n})\n\ntest('user can create a new market', async ({ page }) => {\n  \u002F\u002F 最初にログイン\n  await page.goto('\u002Fcreator-dashboard')\n\n  \u002F\u002F 市場作成フォームに入力\n  await page.fill('input[name=\"name\"]', 'Test Market')\n  await page.fill('textarea[name=\"description\"]', 'Test description')\n  await page.fill('input[name=\"endDate\"]', '2025-12-31')\n\n  \u002F\u002F フォームを送信\n  await page.click('button[type=\"submit\"]')\n\n  \u002F\u002F 成功メッセージを確認\n  await expect(page.locator('text=Market created successfully')).toBeVisible()\n\n  \u002F\u002F 市場ページへのリダイレクトを確認\n  await expect(page).toHaveURL(\u002F\\\u002Fmarkets\\\u002Ftest-market\u002F)\n})\n```\n\n## テストファイル構成\n\n```\nsrc\u002F\n├── components\u002F\n│   ├── Button\u002F\n│   │   ├── Button.tsx\n│   │   ├── Button.test.tsx          # ユニットテスト\n│   │   └── Button.stories.tsx       # Storybook\n│   └── MarketCard\u002F\n│       ├── MarketCard.tsx\n│       └── MarketCard.test.tsx\n├── app\u002F\n│   └── api\u002F\n│       └── markets\u002F\n│           ├── route.ts\n│           └── route.test.ts         # 統合テスト\n└── e2e\u002F\n    ├── markets.spec.ts               # E2Eテスト\n    ├── trading.spec.ts\n    └── auth.spec.ts\n```\n\n## 外部サービスのモック\n\n### Supabaseモック\n```typescript\njest.mock('@\u002Flib\u002Fsupabase', () => ({\n  supabase: {\n    from: jest.fn(() => ({\n      select: jest.fn(() => ({\n        eq: jest.fn(() => Promise.resolve({\n          data: [{ id: 1, name: 'Test Market' }],\n          error: null\n        }))\n      }))\n    }))\n  }\n}))\n```\n\n### Redisモック\n```typescript\njest.mock('@\u002Flib\u002Fredis', () => ({\n  searchMarketsByVector: jest.fn(() => Promise.resolve([\n    { slug: 'test-market', similarity_score: 0.95 }\n  ])),\n  checkRedisHealth: jest.fn(() => Promise.resolve({ connected: true }))\n}))\n```\n\n### OpenAIモック\n```typescript\njest.mock('@\u002Flib\u002Fopenai', () => ({\n  generateEmbedding: jest.fn(() => Promise.resolve(\n    new Array(1536).fill(0.1) \u002F\u002F 1536次元埋め込みをモック\n  ))\n}))\n```\n\n## テストカバレッジ検証\n\n### カバレッジレポートを実行\n```bash\nnpm run test:coverage\n```\n\n### カバレッジ閾値\n```json\n{\n  \"jest\": {\n    \"coverageThresholds\": {\n      \"global\": {\n        \"branches\": 80,\n        \"functions\": 80,\n        \"lines\": 80,\n        \"statements\": 80\n      }\n    }\n  }\n}\n```\n\n## 避けるべき一般的なテストの誤り\n\n### ❌ 誤り：実装の詳細をテスト\n```typescript\n\u002F\u002F 内部状態をテストしない\nexpect(component.state.count).toBe(5)\n```\n\n### ✅ 正解：ユーザーに見える動作をテスト\n```typescript\n\u002F\u002F ユーザーが見るものをテスト\nexpect(screen.getByText('Count: 5')).toBeInTheDocument()\n```\n\n### ❌ 誤り：脆弱なセレクタ\n```typescript\n\u002F\u002F 簡単に壊れる\nawait page.click('.css-class-xyz')\n```\n\n### ✅ 正解：セマンティックセレクタ\n```typescript\n\u002F\u002F 変更に強い\nawait page.click('button:has-text(\"Submit\")')\nawait page.click('[data-testid=\"submit-button\"]')\n```\n\n### ❌ 誤り：テストの分離なし\n```typescript\n\u002F\u002F テストが互いに依存\ntest('creates user', () => { \u002F* ... *\u002F })\ntest('updates same user', () => { \u002F* 前のテストに依存 *\u002F })\n```\n\n### ✅ 正解：独立したテスト\n```typescript\n\u002F\u002F 各テストが独自のデータをセットアップ\ntest('creates user', () => {\n  const user = createTestUser()\n  \u002F\u002F テストロジック\n})\n\ntest('updates user', () => {\n  const user = createTestUser()\n  \u002F\u002F 更新ロジック\n})\n```\n\n## 継続的テスト\n\n### 開発中のウォッチモード\n```bash\nnpm test -- --watch\n# ファイル変更時に自動的にテストが実行される\n```\n\n### プリコミットフック\n```bash\n# すべてのコミット前に実行\nnpm test && npm run lint\n```\n\n### CI\u002FCD統合\n```yaml\n# GitHub Actions\n- name: Run Tests\n  run: npm test -- --coverage\n- name: Upload Coverage\n  uses: codecov\u002Fcodecov-action@v3\n```\n\n## ベストプラクティス\n\n1. **テストを最初に書く** - 常にTDD\n2. **テストごとに1つのアサート** - 単一の動作に焦点\n3. **説明的なテスト名** - テスト内容を説明\n4. **Arrange-Act-Assert** - 明確なテスト構造\n5. **外部依存関係をモック** - ユニットテストを分離\n6. **エッジケースをテスト** - null、undefined、空、大きい値\n7. **エラーパスをテスト** - ハッピーパスだけでなく\n8. **テストを高速に保つ** - ユニットテスト各50ms未満\n9. **テスト後にクリーンアップ** - 副作用なし\n10. **カバレッジレポートをレビュー** - ギャップを特定\n\n## 成功指標\n\n- 80%以上のコードカバレッジを達成\n- すべてのテストが成功（グリーン）\n- スキップまたは無効化されたテストなし\n- 高速なテスト実行（ユニットテストは30秒未満）\n- E2Eテストがクリティカルなユーザーフローをカバー\n- テストが本番前にバグを検出\n\n---\n\n**覚えておいてください**：テストはオプションではありません。テストは自信を持ってリファクタリングし、迅速に開発し、本番の信頼性を可能にする安全網です。\n","# テスト駆動開発ワークフロー\n\nこのスキルは、すべてのコード開発が包括的なテストカバレッジを備えたTDDの原則に従うことを保証します。\n\n## 有効化するタイミング\n\n- 新機能や機能の作成\n- バグや問題の修正\n- 既存コードのリファクタリング\n- APIエンドポイントの追加\n- 新しいコンポーネントの作成\n\n## コア原則\n\n### 1. コードの前にテスト\n常にテストを最初に書き、次にテストに合格するコードを実装します。\n\n### 2. カバレッジ要件\n- 最低80%のカバレッジ（ユニット + 統合 + E2E）\n- すべてのエッジケースをカバー\n- エラーシナリオのテスト\n- 境界条件の検証\n\n### 3. テストタイプ\n\n#### ユニットテスト\n- 個々の関数とユーティリティ\n- コンポーネントロジック\n- 純粋関数\n- ヘルパーとユーティリティ\n\n#### 統合テスト\n- APIエンドポイント\n- データベース操作\n- サービス間相互作用\n- 外部API呼び出し\n\n#### E2Eテスト (Playwright)\n- クリティカルなユーザーフロー\n- 完全なワークフロー\n- ブラウザ自動化\n- UI相互作用\n\n## TDDワークフローステップ\n\n### ステップ1：ユーザージャーニーを書く\n```\n[役割]として、[行動]をしたい、それによって[利益]を得られるようにするため\n\n例：\nユーザーとして、セマンティックに市場を検索したい、\nそれによって正確なキーワードなしでも関連する市場を見つけられるようにするため。\n```\n\n### ステップ2：テストケースを生成\n各ユーザージャーニーについて、包括的なテストケースを作成：\n\n```typescript\ndescribe('Semantic Search', () => {\n  it('returns relevant markets for query', async () => {\n    \u002F\u002F テスト実装\n  })\n\n  it('handles empty query gracefully', async () => {\n    \u002F\u002F エッジケースのテスト\n  })\n\n  it('falls back to substring search when Redis unavailable', async () => {\n    \u002F\u002F フォールバック動作のテスト\n  })\n\n  it('sorts results by similarity score', async () => {\n    \u002F\u002F ソートロジックのテスト\n  })\n})\n```\n\n### ステップ3：テストを実行（失敗するはず）\n```bash\nnpm test\n# テストは失敗するはず - まだ実装していない\n```\n\n### ステップ4：コードを実装\nテストに合格する最小限のコードを書く：\n\n```typescript\n\u002F\u002F テストにガイドされた実装\nexport async function searchMarkets(query: string) {\n  \u002F\u002F 実装はここ\n}\n```\n\n### ステップ5：テストを再実行\n```bash\nnpm test\n# テストは今度は成功するはず\n```\n\n### ステップ6：リファクタリング\nテストをグリーンに保ちながらコード品質を向上：\n- 重複を削除\n- 命名を改善\n- パフォーマンスを最適化\n- 可読性を向上\n\n### ステップ7：カバレッジを確認\n```bash\nnpm run test:coverage\n# 80%以上のカバレッジを達成したことを確認\n```\n\n## テストパターン\n\n### ユニットテストパターン (Jest\u002FVitest)\n```typescript\nimport { render, screen, fireEvent } from '@testing-library\u002Freact'\nimport { Button } from '.\u002FButton'\n\ndescribe('Button Component', () => {\n  it('renders with correct text', () => {\n    render(\u003CButton>Click me\u003C\u002FButton>)\n    expect(screen.getByText('Click me')).toBeInTheDocument()\n  })\n\n  it('calls onClick when clicked', () => {\n    const handleClick = jest.fn()\n    render(\u003CButton onClick={handleClick}>Click\u003C\u002FButton>)\n\n    fireEvent.click(screen.getByRole('button'))\n\n    expect(handleClick).toHaveBeenCalledTimes(1)\n  })\n\n  it('is disabled when disabled prop is true', () => {\n    render(\u003CButton disabled>Click\u003C\u002FButton>)\n    expect(screen.getByRole('button')).toBeDisabled()\n  })\n})\n```\n\n### API統合テストパターン\n```typescript\nimport { NextRequest } from 'next\u002Fserver'\nimport { GET } from '.\u002Froute'\n\ndescribe('GET \u002Fapi\u002Fmarkets', () => {\n  it('returns markets successfully', async () => {\n    const request = new NextRequest('http:\u002F\u002Flocalhost\u002Fapi\u002Fmarkets')\n    const response = await GET(request)\n    const data = await response.json()\n\n    expect(response.status).toBe(200)\n    expect(data.success).toBe(true)\n    expect(Array.isArray(data.data)).toBe(true)\n  })\n\n  it('validates query parameters', async () => {\n    const request = new NextRequest('http:\u002F\u002Flocalhost\u002Fapi\u002Fmarkets?limit=invalid')\n    const response = await GET(request)\n\n    expect(response.status).toBe(400)\n  })\n\n  it('handles database errors gracefully', async () => {\n    \u002F\u002F データベース障害をモック\n    const request = new NextRequest('http:\u002F\u002Flocalhost\u002Fapi\u002Fmarkets')\n    \u002F\u002F エラー処理のテスト\n  })\n})\n```\n\n### E2Eテストパターン (Playwright)\n```typescript\nimport { test, expect } from '@playwright\u002Ftest'\n\ntest('user can search and filter markets', async ({ page }) => {\n  \u002F\u002F 市場ページに移動\n  await page.goto('\u002F')\n  await page.click('a[href=\"\u002Fmarkets\"]')\n\n  \u002F\u002F ページが読み込まれたことを確認\n  await expect(page.locator('h1')).toContainText('Markets')\n\n  \u002F\u002F 市場を検索\n  await page.fill('input[placeholder=\"Search markets\"]', 'election')\n\n  \u002F\u002F デバウンスと結果を待つ\n  await page.waitForTimeout(600)\n\n  \u002F\u002F 検索結果が表示されることを確認\n  const results = page.locator('[data-testid=\"market-card\"]')\n  await expect(results).toHaveCount(5, { timeout: 5000 })\n\n  \u002F\u002F 結果に検索語が含まれることを確認\n  const firstResult = results.first()\n  await expect(firstResult).toContainText('election', { ignoreCase: true })\n\n  \u002F\u002F ステータスでフィルタリング\n  await page.click('button:has-text(\"Active\")')\n\n  \u002F\u002F フィルタリングされた結果を確認\n  await expect(results).toHaveCount(3)\n})\n\ntest('user can create a new market', async ({ page }) => {\n  \u002F\u002F 最初にログイン\n  await page.goto('\u002Fcreator-dashboard')\n\n  \u002F\u002F 市場作成フォームに入力\n  await page.fill('input[name=\"name\"]', 'Test Market')\n  await page.fill('textarea[name=\"description\"]', 'Test description')\n  await page.fill('input[name=\"endDate\"]', '2025-12-31')\n\n  \u002F\u002F フォームを送信\n  await page.click('button[type=\"submit\"]')\n\n  \u002F\u002F 成功メッセージを確認\n  await expect(page.locator('text=Market created successfully')).toBeVisible()\n\n  \u002F\u002F 市場ページへのリダイレクトを確認\n  await expect(page).toHaveURL(\u002F\\\u002Fmarkets\\\u002Ftest-market\u002F)\n})\n```\n\n## テストファイル構成\n\n```\nsrc\u002F\n├── components\u002F\n│   ├── Button\u002F\n│   │   ├── Button.tsx\n│   │   ├── Button.test.tsx          # ユニットテスト\n│   │   └── Button.stories.tsx       # Storybook\n│   └── MarketCard\u002F\n│       ├── MarketCard.tsx\n│       └── MarketCard.test.tsx\n├── app\u002F\n│   └── api\u002F\n│       └── markets\u002F\n│           ├── route.ts\n│           └── route.test.ts         # 統合テスト\n└── e2e\u002F\n    ├── markets.spec.ts               # E2Eテスト\n    ├── trading.spec.ts\n    └── auth.spec.ts\n```\n\n## 外部サービスのモック\n\n### Supabaseモック\n```typescript\njest.mock('@\u002Flib\u002Fsupabase', () => ({\n  supabase: {\n    from: jest.fn(() => ({\n      select: jest.fn(() => ({\n        eq: jest.fn(() => Promise.resolve({\n          data: [{ id: 1, name: 'Test Market' }],\n          error: null\n        }))\n      }))\n    }))\n  }\n}))\n```\n\n### Redisモック\n```typescript\njest.mock('@\u002Flib\u002Fredis', () => ({\n  searchMarketsByVector: jest.fn(() => Promise.resolve([\n    { slug: 'test-market', similarity_score: 0.95 }\n  ])),\n  checkRedisHealth: jest.fn(() => Promise.resolve({ connected: true }))\n}))\n```\n\n### OpenAIモック\n```typescript\njest.mock('@\u002Flib\u002Fopenai', () => ({\n  generateEmbedding: jest.fn(() => Promise.resolve(\n    new Array(1536).fill(0.1) \u002F\u002F 1536次元埋め込みをモック\n  ))\n}))\n```\n\n## テストカバレッジ検証\n\n### カバレッジレポートを実行\n```bash\nnpm run test:coverage\n```\n\n### カバレッジ閾値\n```json\n{\n  \"jest\": {\n    \"coverageThresholds\": {\n      \"global\": {\n        \"branches\": 80,\n        \"functions\": 80,\n        \"lines\": 80,\n        \"statements\": 80\n      }\n    }\n  }\n}\n```\n\n## 避けるべき一般的なテストの誤り\n\n### ❌ 誤り：実装の詳細をテスト\n```typescript\n\u002F\u002F 内部状態をテストしない\nexpect(component.state.count).toBe(5)\n```\n\n### ✅ 正解：ユーザーに見える動作をテスト\n```typescript\n\u002F\u002F ユーザーが見るものをテスト\nexpect(screen.getByText('Count: 5')).toBeInTheDocument()\n```\n\n### ❌ 誤り：脆弱なセレクタ\n```typescript\n\u002F\u002F 簡単に壊れる\nawait page.click('.css-class-xyz')\n```\n\n### ✅ 正解：セマンティックセレクタ\n```typescript\n\u002F\u002F 変更に強い\nawait page.click('button:has-text(\"Submit\")')\nawait page.click('[data-testid=\"submit-button\"]')\n```\n\n### ❌ 誤り：テストの分離なし\n```typescript\n\u002F\u002F テストが互いに依存\ntest('creates user', () => { \u002F* ... *\u002F })\ntest('updates same user', () => { \u002F* 前のテストに依存 *\u002F })\n```\n\n### ✅ 正解：独立したテスト\n```typescript\n\u002F\u002F 各テストが独自のデータをセットアップ\ntest('creates user', () => {\n  const user = createTestUser()\n  \u002F\u002F テストロジック\n})\n\ntest('updates user', () => {\n  const user = createTestUser()\n  \u002F\u002F 更新ロジック\n})\n```\n\n## 継続的テスト\n\n### 開発中のウォッチモード\n```bash\nnpm test -- --watch\n# ファイル変更時に自動的にテストが実行される\n```\n\n### プリコミットフック\n```bash\n# すべてのコミット前に実行\nnpm test && npm run lint\n```\n\n### CI\u002FCD統合\n```yaml\n# GitHub Actions\n- name: Run Tests\n  run: npm test -- --coverage\n- name: Upload Coverage\n  uses: codecov\u002Fcodecov-action@v3\n```\n\n## ベストプラクティス\n\n1. **テストを最初に書く** - 常にTDD\n2. **テストごとに1つのアサート** - 単一の動作に焦点\n3. **説明的なテスト名** - テスト内容を説明\n4. **Arrange-Act-Assert** - 明確なテスト構造\n5. **外部依存関係をモック** - ユニットテストを分離\n6. **エッジケースをテスト** - null、undefined、空、大きい値\n7. **エラーパスをテスト** - ハッピーパスだけでなく\n8. **テストを高速に保つ** - ユニットテスト各50ms未満\n9. **テスト後にクリーンアップ** - 副作用なし\n10. **カバレッジレポートをレビュー** - ギャップを特定\n\n## 成功指標\n\n- 80%以上のコードカバレッジを達成\n- すべてのテストが成功（グリーン）\n- スキップまたは無効化されたテストなし\n- 高速なテスト実行（ユニットテストは30秒未満）\n- E2Eテストがクリティカルなユーザーフローをカバー\n- テストが本番前にバグを検出\n\n---\n\n**覚えておいてください**：テストはオプションではありません。テストは自信を持ってリファクタリングし、迅速に開発し、本番の信頼性を可能にする安全網です。\n",{"name":5,"description":7},"main","7b610356e36623652299fa2acb477ff821b1d920","upstream-sync\u002Fwork\u002Fecc\u002Fdocs\u002Fja-JP\u002Fskills\u002Ftdd-workflow",0,"https:\u002F\u002Fgithub.com\u002Foabdelmaksoud\u002FSuperClaw","https:\u002F\u002Fgithub.com\u002Foabdelmaksoud","https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Fo-abdelmaksoud\u002F","Full-Stack Engineer | AI Systems Architect | Building autonomous multi-agent systems","2026-03-08 21:12:53",{"source":8,"skillName":5,"commands":37,"prompt":47,"zipAvailable":48},[38,41,44],{"tool":39,"command":40},"npx","npx skills add oabdelmaksoud\u002FSuperClaw --skill tdd-workflow",{"tool":42,"command":43},"bunx","bunx skills add oabdelmaksoud\u002FSuperClaw --skill tdd-workflow",{"tool":45,"command":46},"pnpm","pnpm dlx skills add oabdelmaksoud\u002FSuperClaw --skill tdd-workflow","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Foabdelmaksoud\u002FSuperClaw\u002Fblob\u002Fmain\u002Fupstream-sync\u002Fwork\u002Fecc\u002Fdocs\u002Fja-JP\u002Fskills\u002Ftdd-workflow\u002FSKILL.md",true,[],[51,72,86,113,139,158],{"skillNo":52,"name":53,"nameZh":6,"description":54,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":55,"categories":56,"keywords":62,"publishedAt":22},"01M6D88QCPTBZVCRED0NZ1Y8K8","visa-doc-translate","Translate visa application documents (images) to English and create a bilingual PDF with original and translation","https:\u002F\u002Fgithub.com\u002Foabdelmaksoud\u002FSuperClaw\u002Fblob\u002Fmain\u002Fupstream-sync\u002Fwork\u002Fecc\u002Fskills\u002Fvisa-doc-translate\u002FSKILL.md",[57],{"categoryNo":58,"categoryName":59,"taxonomyType":60,"taxonomyTypeDesc":61},"01JBSEEDCAT000000000000002","文档处理","SCENARIO","使用场景",[63,64,65,66,67,68,69,70,71],"translate","doc","visa doc translate","translation","application","create","images","PDF","documents",{"skillNo":73,"name":74,"nameZh":6,"description":75,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":76,"categories":77,"keywords":78,"publishedAt":22},"01M6D88NBM95T3TFM50CYYAP65","verification-loop","A comprehensive verification system for Claude Code sessions.","https:\u002F\u002Fgithub.com\u002Foabdelmaksoud\u002FSuperClaw\u002Fblob\u002Fmain\u002Fupstream-sync\u002Fwork\u002Fecc\u002Fskills\u002Fverification-loop\u002FSKILL.md",[],[79,80,81,82,83,84,85],"verification","loop","verification loop","sessions","code","claude code sessions","system",{"skillNo":87,"name":5,"nameZh":6,"description":88,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":89,"categories":90,"keywords":102,"publishedAt":22},"01M6D88JFZ2P996GVRHJNSZSTM","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\u002Foabdelmaksoud\u002FSuperClaw\u002Fblob\u002Fmain\u002Fupstream-sync\u002Fwork\u002Fecc\u002Fskills\u002Ftdd-workflow\u002FSKILL.md",[91,94,97],{"categoryNo":92,"categoryName":93,"taxonomyType":60,"taxonomyTypeDesc":61},"01JBSEEDCAT000000000000008","测试与质量",{"categoryNo":95,"categoryName":96,"taxonomyType":60,"taxonomyTypeDesc":61},"01JBSEEDCAT000000000000023","Skill与智能体开发",{"categoryNo":98,"categoryName":99,"taxonomyType":100,"taxonomyTypeDesc":101},"01JBSEEDCAT000000000000030","开发工程师","PROFESSION","适用职业",[19,20,21,103,104,105,83,106,107,108,109,110,111,112],"e2e tests","e2e","integration","development","use","test","refactoring","coverage","tests","writing",{"skillNo":114,"name":115,"nameZh":6,"description":116,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":117,"categories":118,"keywords":119,"publishedAt":22},"01M6D88FTHRRSVJMXF2G7MQAK3","swiftui-patterns","SwiftUI architecture patterns, state management with @Observable, view composition, navigation, performance optimization, and modern iOS\u002FmacOS UI best practices.","https:\u002F\u002Fgithub.com\u002Foabdelmaksoud\u002FSuperClaw\u002Fblob\u002Fmain\u002Fupstream-sync\u002Fwork\u002Fecc\u002Fskills\u002Fswiftui-patterns\u002FSKILL.md",[],[120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138],"patterns","swiftui","swiftui patterns","architecture","macos","performance","state management","best practices","state","ui","Optimization","ios","architecture patterns","Composition","performance optimization","view","management","swiftui architecture","navigation",{"skillNo":140,"name":141,"nameZh":6,"description":142,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":143,"categories":144,"keywords":146,"publishedAt":22},"01M6D88D527QTQT9DKHTRFN6EA","swift-protocol-di-testing","Protocol-based dependency injection for testable Swift code — mock file system, network, and external APIs using focused protocols and Swift Testing.","https:\u002F\u002Fgithub.com\u002Foabdelmaksoud\u002FSuperClaw\u002Fblob\u002Fmain\u002Fupstream-sync\u002Fwork\u002Fecc\u002Fskills\u002Fswift-protocol-di-testing\u002FSKILL.md",[145],{"categoryNo":92,"categoryName":93,"taxonomyType":60,"taxonomyTypeDesc":61},[147,148,149,150,83,151,152,153,154,85,155,156,157],"swift protocol di testing","protocol","swift","testing","protocols","file","network","injection","dependency","swift testing","dependency injection",{"skillNo":159,"name":160,"nameZh":6,"description":161,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":162,"categories":163,"keywords":164,"publishedAt":22},"01M6D88AJW8H2QNWSW5ZY82R43","swift-concurrency-6-2","Swift 6.2 Approachable Concurrency — single-threaded by default, @concurrent for explicit background offloading, isolated conformances for main actor types.","https:\u002F\u002Fgithub.com\u002Foabdelmaksoud\u002FSuperClaw\u002Fblob\u002Fmain\u002Fupstream-sync\u002Fwork\u002Fecc\u002Fskills\u002Fswift-concurrency-6-2\u002FSKILL.md",[],[165,166,149,167,168,27],"concurrency","swift concurrency","swift concurrency 6 2","default"]