mcpField
A
api-contract-testing

api-contract-testing

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

api-contract-testing について

API が利用側と提供側の合意に沿っているかを確認するテストスキルです。Pact によるコンシューマー駆動テスト、提供側の検証、OpenAPI スキーマ検証を扱います。

主な機能

  1. 01Pact によるコンシューマー駆動テスト
  2. 02提供側の検証
  3. 03OpenAPI のリクエストとレスポンス検証
  4. 04複数言語エコシステムのガイド

活用シーン

  1. 01依存サービス間の API 合意の確認
  2. 02公開済み契約に対する提供側の動作検証
  3. 03OpenAPI による Express の入出力検証

インストール

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

$npx skills add https://github.com/secondsky/claude-skills --skill api-contract-testing

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

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
java-rest-assured.md
pact-broker-cicd.md
python-json-schema.md

詳細

API コントラクトテスト

完全な統合テストを実施せずに、API がコンシューマーとプロバイダー間のコントラクトに従っていることを検証します。

主な概念

用語定義
コンシューマーAPI を呼び出すサービス
プロバイダーAPI を公開するサービス
コントラクト合意されたリクエスト/レスポンス形式
Pactコンシューマー主導のコントラクトテストツール
スキーマ構造の定義(OpenAPI、JSON Schema)
ブローカーコントラクトの中央リポジトリ

Pact コンシューマーテスト(TypeScript)

import { PactV3, MatchersV3 } from '@pact-foundation/pact';

const provider = new PactV3({
  consumer: 'OrderService',
  provider: 'UserService'
});

describe('User API Contract', () => {
  it('returns user by ID', async () => {
    await provider
      .given('user 123 exists')
      .uponReceiving('a request for user 123')
      .withRequest({ method: 'GET', path: '/users/123' })
      .willRespondWith({
        status: 200,
        body: MatchersV3.like({
          id: '123',
          name: MatchersV3.string('John'),
          email: MatchersV3.email('[email protected]')
        })
      })
      .executeTest(async (mockServer) => {
        const response = await fetch(`${mockServer.url}/users/123`);
        expect(response.status).toBe(200);
      });
  });

  it('returns 404 for non-existent user', async () => {
    await provider
      .given('user does not exist')
      .uponReceiving('a request for non-existent user')
      .withRequest({ method: 'GET', path: '/users/999' })
      .willRespondWith({
        status: 404,
        body: MatchersV3.like({
          error: { code: 'NOT_FOUND', message: MatchersV3.string() }
        })
      })
      .executeTest(async (mockServer) => {
        const response = await fetch(`${mockServer.url}/users/999`);
        expect(response.status).toBe(404);
      });
  });
});

プロバイダーの検証

import { Verifier } from '@pact-foundation/pact';

new Verifier({
  provider: 'UserService',
  providerBaseUrl: 'http://localhost:3000',
  pactBrokerUrl: process.env.PACT_BROKER_URL,
  publishVerificationResult: true,
  providerVersion: process.env.GIT_SHA,
  stateHandlers: {
    'user 123 exists': async () => {
      await db.users.create({ id: '123', name: 'John' });
    },
    'user does not exist': async () => {
      await db.users.deleteAll();
    }
  }
}).verifyProvider();

OpenAPI の検証(Express)

const OpenApiValidator = require('express-openapi-validator');

app.use(OpenApiValidator.middleware({
  apiSpec: './openapi.yaml',
  validateRequests: true,
  validateResponses: true,
  validateSecurity: true
}));

その他の実装

ベストプラクティス

実施すること:

  • コンシューマーの視点からテストする
  • 柔軟な照合にはマッチャーを使用する
  • 特定の値ではなく、構造を検証する
  • コントラクトのバージョンを明示する
  • エラーレスポンスをテストする
  • CI パイプラインでテストを実行する
  • 後方互換性をテストする

実施しないこと:

  • コントラクトでビジネスロジックをテストする
  • 特定の値をハードコードする
  • エラーシナリオを省略する
  • バージョン管理を無視する
  • 検証せずにデプロイする

ツール

  • Pact - 複数言語に対応したコンシューマー主導のコントラクト
  • Spring Cloud Contract - JVM エコシステム
  • OpenAPI/Swagger - スキーマファーストの検証
  • Dredd - API Blueprint のテスト
  • Spectral - OpenAPI のリンティング

コメント