【ツール活用|実務向け】消費者主導契約(CDC)で防ぐAPIの破壊的変更 — Pactを用いたテスト自動化の実践

1. 導入:なぜCDCが必要なのか

マイクロサービス環境では、サービス間の依存関係が複雑になりがちです。バックエンド側のAPI仕様を少し変更しただけで、フロントエンドや他サービスの機能が突然停止する「破壊的変更(Breaking Change)」は、開発現場で最も避けたいトラブルの一つです。Consumer Driven Contracts (CDC) は、APIの「利用者(Consumer)」が求めるデータ構造をあらかじめ定義し、それをテストとして組み込むことで、サービス間の結合を安全に保つための強力な解決策となります。

2. 基礎知識:CDCとPactの仕組み

CDCは、「消費者(Consumer)」が「提供者(Provider)」に対して「これだけのデータ項目が必要だ」という契約(Contract)を定義する手法です。
関連する主要用語は以下の通りです。
Pact: CDCを実装するための最も標準的なツール群。Consumer側でテストを実行して契約ファイル(JSON)を生成し、それをProvider側で検証します。
破壊的変更の防止: ProviderがAPIを変更した際、既存の契約に違反していないかをCI/CDパイプラインで自動検知します。これにより、リリース前の早期段階でバグを見つけることが可能です。

3. 実装/解決策:Pactを用いたテストフロー

CDCの導入には、以下のステップが一般的です。
1. Consumer側でPactテストを実行し、「Pactファイル(契約書)」を作成。
2. Pactファイル(JSON)をPact Broker(契約管理サーバー)にアップロード。
3. Provider側でPact Brokerから契約を取得し、自身のAPIがその内容を満たしているかを検証する。

4. サンプルプログラム:Consumer側のテストコード例

以下は、Node.js環境(Jest)でPactを使用して、ユーザー情報を取得するAPIの契約を作成する例です。

const { Pact } = require('@pact-foundation/pact');
const path = require('path');

// 契約の定義
const provider = new Pact({
  consumer: 'Frontend-App',
  provider: 'User-Service',
  port: 4000,
  log: path.resolve(process.cwd(), 'logs', 'pact.log'),
  dir: path.resolve(process.cwd(), 'pacts'),
});

describe('User API 契約テスト', () => {
  beforeAll(() => provider.setup());
  afterAll(() => provider.finalize());

  it('ユーザーIDを指定して詳細を取得する', async () => {
    // 期待するレスポンスの構造を定義
    const expectedResponse = {
      id: 1,
      name: 'Test User'
    };

    // モックサーバーの設定
    await provider.addInteraction({
      state: 'ユーザーID 1 が存在する',
      uponReceiving: 'ユーザー詳細取得リクエスト',
      withRequest: { method: 'GET', path: '/users/1' },
      willRespondWith: {
        status: 200,
        body: expectedResponse,
      },
    });

    // 実際にAPIを叩く処理(実際にはaxios等を使用)
    // const response = await apiClient.getUser(1);
    // expect(response.data).toEqual(expectedResponse);
  });
});

5. 応用・注意点:現場での運用ポイント

契約の進化: APIの仕様変更は避けられません。変更が必要な場合は、まずConsumer側で契約(Pactファイル)を更新し、Provider側のテストを失敗させてからコード修正を行うという「契約ベースのワークフロー」を定着させることが重要です。
Pact Brokerの活用: 契約書を手渡しで管理するのは非効率です。Pact Brokerを導入して、誰がどのAPIのどのバージョンを必要としているかを一元管理しましょう。
陥りやすい罠: 契約を過剰に厳格に定義しすぎると、ちょっとしたレスポンスの追加(非破壊的な変更)でテストが落ちるようになります。必要な項目のみを契約に含める「疎結合な契約」を心がけるのが、運用を長続きさせるコツです。

コメント

タイトルとURLをコピーしました