mcpField
T
test-quality-analysis

test-quality-analysis

github.com/secondskyテスト・品質240455 回インストール5 週間前に更新
リポジトリ

test-quality-analysis について

テストスイートのレビューと改善を支援する、テスト品質分析スキルです。テストの匂いやアンチパターンの見つけ方に加え、信頼性、アサーション、モック、カバレッジ、保守性に関する指針を示します。

主な機能

  1. 01過剰なモックとテストの匂いを検出
  2. 02不安定で壊れやすいテストを特定
  3. 03アサーションの具体性を向上
  4. 04カバレッジと重要経路を確認
  5. 05モックと単体テストの指針
  6. 06コードレビュー用チェックリスト

活用シーン

  1. 01テストスイートの過剰なモックを点検
  2. 02断続的に失敗するテストを調査
  3. 03アサーションとエラー経路のカバレッジを強化
  4. 04コードレビューでテスト品質を評価

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/secondsky/claude-skills --skill test-quality-analysis

インストール後、Claude Code で/test-quality-analysisを入力して読み込まれたか確認します。

詳細

テスト品質の分析

テストの不吉な臭い、過剰なモック、カバレッジ不足、テストのアンチパターンを検出し、テスト品質を分析・向上させるための専門知識です。

主な評価軸

  • 正確性:テストが正しい振る舞いを検証していること
  • 信頼性:テストが決定的で、不安定でないこと
  • 保守性:テストが理解しやすいこと
  • パフォーマンス:テストがすばやく実行されること
  • カバレッジ:テストが重要なコードパスを網羅していること
  • 独立性:テストが外部の状態に依存しないこと

テストの不吉な臭い

過剰なモック

問題:依存関係をモックしすぎると、テストが壊れやすくなります。

// ❌ BAD: Overmocked
test('calculate total', () => {
  const mockAdd = vi.fn(() => 10)
  const mockMultiply = vi.fn(() => 20)
  // Testing implementation, not behavior
})

// ✅ GOOD: Mock only external dependencies
test('calculate order total', () => {
  const mockPricingAPI = vi.fn(() => ({ tax: 0.1 }))
  const total = calculateTotal(order, mockPricingAPI)
  expect(total).toBe(38)
})

検出方法:モックが3〜4個を超えている、純粋関数をモックしている、複雑なモックのセットアップが必要になっている。

対処方法:I/O の境界(API、データベース、ファイルシステム)のみをモックします。

壊れやすいテスト

問題:無関係なコードの変更によってテストが失敗します。

// ❌ BAD: Tests implementation details
await page.locator('.form-container > div:nth-child(2) > button').click()

// ✅ GOOD: Semantic selector
await page.getByRole('button', { name: 'Submit' }).click()
不安定なテスト

問題:テストの成否が非決定的です。

// ❌ BAD: Race condition
test('loads data', async () => {
  fetchData()
  await new Promise(resolve => setTimeout(resolve, 1000))
  expect(data).toBeDefined()
})

// ✅ GOOD: Proper async handling
test('loads data', async () => {
  const data = await fetchData()
  expect(data).toBeDefined()
})
不適切なアサーション
// ❌ BAD: Weak assertion
test('returns users', async () => {
  const users = await getUsers()
  expect(users).toBeDefined() // Too vague!
})

// ✅ GOOD: Strong, specific assertions
test('creates user with correct attributes', async () => {
  const user = await createUser({ name: 'John' })
  expect(user).toMatchObject({
    id: expect.any(Number),
    name: 'John',
  })
})

分析ツール

# Vitest coverage (prefer bun)
bun test --coverage
open coverage/index.html

# Check thresholds
bun test --coverage --coverage.thresholds.lines=80

# pytest-cov (Python)
uv run pytest --cov --cov-report=html
open htmlcov/index.html

ベストプラクティスのチェックリスト

単体テストの品質(FIRST)
  • 高速:テストが数ミリ秒で実行される
  • 独立:テスト間に依存関係がない
  • 再現可能:毎回同じ結果になる
  • 自己検証可能:合否が明確である
  • 適時:コードと同時に作成される
モックのガイドライン
  • 外部依存関係のみをモックする
  • ビジネスロジックや純粋関数はモックしない
  • 可能な場合は実際の実装を使用する
  • 1つのテストにつきモックは最大3〜4個に制限する
カバレッジの目標
  • ビジネスロジックの行カバレッジを80%以上にする
  • 重要なパス(認証、支払い)は100%にする
  • すべてのエラーパスをテストする
  • 境界条件をテストする
テストの構成(AAA パターン)
test('user registration', async () => {
  // Arrange
  const userData = { email: '[email protected]' }

  // Act
  const user = await registerUser(userData)

  // Assert
  expect(user.email).toBe('[email protected]')
})

コードレビューのチェックリスト

  • テストが実装ではなく振る舞いを検証している
  • アサーションが具体的で意味のあるものになっている
  • 不安定なテスト(タイミングや順序の問題)がない
  • async/await が適切に使われている
  • テスト名から振る舞いが明確にわかる
  • コードの重複が最小限である
  • 重要なパスにテストがある
  • 正常系とエラーケースの両方が網羅されている

よくあるアンチパターン

実装の詳細をテストする
// ❌ BAD
const spy = vi.spyOn(Math, 'sqrt')
calculateDistance()
expect(spy).toHaveBeenCalled() // Testing how, not what

// ✅ GOOD
const distance = calculateDistance({ x: 0, y: 0 }, { x: 3, y: 4 })
expect(distance).toBe(5) // Testing output
モックの過剰な使用
// ❌ BAD
const mockAdd = vi.fn((a, b) => a + b)

// ✅ GOOD: Use real implementations
import { add } from './utils'
// Only mock external services
const mockPaymentGateway = vi.fn()

関連項目

  • vitest-testing - TypeScript/JavaScript のテスト
  • playwright-testing - E2E テスト
  • mutation-testing - テストの有効性を検証する

コメント