mcpField
Q
qe-api-testing-patterns

qe-api-testing-patterns

github.com/proffesor-for-testingテスト・品質51988 回インストール今日更新
リポジトリ

qe-api-testing-patterns について

qe-api-testing-patternsは、APIをテストするチームやテスト戦略を設計する人向けのスキルです。契約・コンポーネント・統合テストと、認証、入力検証、エラー、冪等性、並行処理のパターンを扱います。

主な機能

  1. 01契約・コンポーネント・統合テスト
  2. 02コンシューマー視点の契約検証
  3. 03認証と入力検証のテスト
  4. 04エラーと冪等性のシナリオ
  5. 05並行処理とCRUDのパターン
  6. 06APIテスト自動化のガイド

活用シーン

  1. 01マイクロサービスの契約テスト
  2. 02RESTやGraphQLの挙動検証
  3. 03認証と障害処理の確認
  4. 04CI/CD向けAPIテストの計画

インストール

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

$npx skills add https://github.com/proffesor-for-testing/agentic-qe --skill qe-api-testing-patterns

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

詳細

API テストパターン

<default_to_action> API をテストする場合、または API テスト戦略を設計する場合:

  1. テストレベルを特定します:コントラクト、インテグレーション、またはコンポーネント
  2. 実装ではなく、コントラクトをテストします(コンシューマーの視点)
  3. 認証、入力、エラー、冪等性、並行性を検証します
  4. スキーマ検証を使って CI/CD で自動化します
  5. 本番環境の API を監視し、コントラクトのドリフトを検出します

パターンのクイック選択:

  • マイクロサービス → コンシューマー主導コントラクト(Pact)
  • REST API → CRUD +ページネーション+フィルタリングのテスト
  • GraphQL → クエリ検証+複雑度制限
  • 外部依存関係 → コンポーネントテストでモックを使用
  • パフォーマンス → 重要なエンドポイントの負荷テスト

重要な成功要因:

  • API はコントラクトです。コンシューマーの視点でテストします
  • 成功パスだけでなく、必ずエラーシナリオもテストします
  • 破壊的変更を防ぐため、API テストをバージョン管理します </default_to_action>

クイックリファレンスカード

使用する場面
  • REST API または GraphQL API のテスト
  • マイクロサービスのコントラクト検証
  • API テスト戦略の設計
  • API の破壊的変更の防止
テストレベル
レベル目的依存関係速度
コントラクトプロバイダーとコンシューマー間の合意なし高速
コンポーネント独立した APIモック高速
インテグレーション実際の依存関係データベース、サービス低速
重要なテストシナリオ
シナリオ必須のテスト例
認証401/403 の処理トークンの期限切れ、ユーザーの誤り
入力400 の検証必須フィールドの欠落、型の誤り
エラー500 の適切な処理DB の停止、タイムアウト
冪等性重複の防止同じ冪等性キー
並行性競合状態並列チェックアウト
ツール
  • コントラクト:Pact、Spring Cloud Contract
  • REST:Supertest、REST-assured、Playwright
  • 負荷:k6、Artillery、JMeter
エージェントの連携
  • qe-api-contract-validator:コントラクトを検証し、破壊的変更を検出します
  • qe-test-generator:OpenAPI 仕様からテストを生成します
  • qe-performance-tester:エンドポイントの負荷テストを実施します
  • qe-security-scanner:API のセキュリティテストを実施します

コントラクトテスト

パターン:コンシューマー主導コントラクト

// Consumer defines expectations
const contract = {
  request: { method: 'POST', path: '/orders', body: { productId: 'abc', quantity: 2 } },
  response: { status: 201, body: { orderId: 'string', total: 'number' } }
};

// Provider must fulfill
test('order API meets contract', async () => {
  const response = await api.post('/orders', { productId: 'abc', quantity: 2 });

  expect(response.status).toBe(201);
  expect(response.body).toMatchSchema({
    orderId: expect.any(String),
    total: expect.any(Number)
  });
});

使用する場面: マイクロサービス、分散システム、サードパーティ統合


重要なテストパターン

認証と認可
describe('Auth', () => {
  it('rejects without token', async () => {
    expect((await api.get('/orders')).status).toBe(401);
  });

  it('rejects expired token', async () => {
    const expired = generateExpiredToken();
    expect((await api.get('/orders', { headers: { Authorization: `Bearer ${expired}` } })).status).toBe(401);
  });

  it('blocks cross-user access', async () => {
    const userAToken = generateToken({ userId: 'A' });
    expect((await api.get('/orders/user-B-order', { headers: { Authorization: `Bearer ${userAToken}` } })).status).toBe(403);
  });
});
入力検証
describe('Validation', () => {
  it('validates required fields', async () => {
    const response = await api.post('/orders', { quantity: 2 }); // Missing productId
    expect(response.status).toBe(400);
    expect(response.body.errors).toContain('productId is required');
  });

  it('validates types', async () => {
    expect((await api.post('/orders', { productId: 'abc', quantity: 'two' })).status).toBe(400);
  });

  it('validates ranges', async () => {
    expect((await api.post('/orders', { productId: 'abc', quantity: -5 })).status).toBe(400);
  });
});
冪等性
it('prevents duplicates with idempotency key', async () => {
  const key = 'unique-123';
  const data = { productId: 'abc', quantity: 2 };

  const r1 = await api.post('/orders', data, { headers: { 'Idempotency-Key': key } });
  const r2 = await api.post('/orders', data, { headers: { 'Idempotency-Key': key } });

  expect(r1.body.orderId).toBe(r2.body.orderId); // Same order
});
並行性
it('handles race condition on inventory', async () => {
  const promises = Array(10).fill().map(() =>
    api.post('/orders', { productId: 'abc', quantity: 1 })
  );
  const responses = await Promise.all(promises);
  const successful = responses.filter(r => r.status === 201);

  const inventory = await db.inventory.findById('abc');
  expect(inventory.quantity).toBe(initialQuantity - successful.length);
});

REST CRUD パターン

describe('Product CRUD', () => {
  let productId;

  it('CREATE', async () => {
    const r = await api.post('/products', { name: 'Widget', price: 10 });
    expect(r.status).toBe(201);
    productId = r.body.id;
  });

  it('READ', async () => {
    const r = await api.get(`/products/${productId}`);
    expect(r.body.name).toBe('Widget');
  });

  it('UPDATE', async () => {
    const r = await api.put(`/products/${productId}`, { price: 12 });
    expect(r.body.price).toBe(12);
  });

  it('DELETE', async () => {
    expect((await api.delete(`/products/${productId}`)).status).toBe(204);
    expect((await api.get(`/products/${productId}`)).status).toBe(404);
  });
});

ベストプラクティス

✅ 推奨事項
  • コンシューマーの視点でテストします
  • スキーマ検証を使用します(厳密な値の検証ではなく)
  • エラーシナリオを徹底的にテストします
  • API テストをバージョン管理します
  • CI/CD で自動化します
❌ 避けること
  • コントラクトではなく実装をテストすること
  • HTTP のセマンティクス(ステータスコード)を無視すること
  • ネガティブテストを行わないこと
  • フィールドの順序や余分なフィールドに対してアサーションを行うこと
  • テストに時間がかかること(外部サービスをモックします)

エージェントを活用した API テスト

// Validate contracts
await Task("Contract Validation", {
  spec: 'openapi.yaml',
  endpoint: '/orders',
  checkBreakingChanges: true
}, "qe-api-contract-validator");

// Generate tests from spec
await Task("Generate API Tests", {
  spec: 'openapi.yaml',
  coverage: 'comprehensive',
  include: ['happy-paths', 'input-validation', 'auth-scenarios', 'error-handling']
}, "qe-test-generator");

// Load test
await Task("API Load Test", {
  endpoint: '/orders',
  rps: 1000,
  duration: '5min'
}, "qe-performance-tester");

// Security scan
await Task("API Security Scan", {
  spec: 'openapi.yaml',
  checks: ['sql-injection', 'xss', 'broken-auth', 'rate-limiting']
}, "qe-security-scanner");

エージェント連携のヒント

メモリ名前空間
aqe/api-testing/
├── contracts/*        - API contract definitions
├── generated-tests/*  - Generated test suites
├── validation/*       - Contract validation results
└── performance/*      - Load test results
フリート連携
const apiFleet = await FleetManager.coordinate({
  strategy: 'contract-testing',
  agents: ['qe-api-contract-validator', 'qe-test-generator', 'qe-test-executor'],
  topology: 'mesh'
});

await apiFleet.execute({
  services: [
    { name: 'orders-api', consumers: ['checkout-ui', 'admin-api'] },
    { name: 'payment-api', consumers: ['orders-api'] }
  ]
});

関連スキル


覚えておくこと

API テストとは、実装ではなくコントラクトと動作を検証することです。正しいレスポンス、適切なエラー処理、許容できるパフォーマンスなど、コンシューマーにとって重要な点に注目します。

エージェントを活用する場合: エージェントはコントラクト検証を自動化し、仕様から包括的なテストスイートを生成して、本番環境の API を監視し、ドリフトを検出します。エージェントを活用して、大規模な API 品質の維持に役立てましょう。

コメント