LASSIC Media らしくメディア
コントラクトテスト(Pact)導入を外注で進める
LASSIC IT事業部|元請(プライムベンダー)としてシステム保守・運用を受託
この記事のポイント
- コントラクトテスト(Pact)がマイクロサービス間のAPI連携でなぜ必要になるかを整理します。
- 消費者駆動契約テスト(CDC)の流れとPact Brokerのcan-i-deploy機能を解説します。
- 外注でコントラクトテストを導入する際の委託範囲と発注前の準備事項を紹介します。
目次
コントラクトテスト(Pact)とは何か
コントラクトテスト(Pact)とは、サービス間で送受信するデータの形式や内容についてコンシューマ(データを利用する側)とプロバイダ(データを提供する側)が合意した「契約」に、実際の実装が適合しているかを個別に検証するテスト手法です*1。契約テストの公式ツールであるPactは、消費者駆動契約テスト(Consumer-Driven Contract Testing、以下CDC)というアプローチを採用しており、コンシューマ側の自動テストを実行する過程で契約(Pactファイル)が自動生成される点が特徴です*1。
Pactの用語では、データを受け取りたい側を「コンシューマ」、必要なデータを提供する側を「API」を意味する「プロバイダ」と呼びます*1。マイクロサービス環境では従来の「クライアント/サーバー」という呼び方より、この役割分担のほうが実態に即すると公式ドキュメントは説明しています*1。OpenAPIのようなスキーマ仕様書が「あるべき姿」を静的に記述するのに対し、Pactは「具体的なリクエストとレスポンスの組み合わせを実行可能なテストケース集合として持つ」点が異なります*1。
マイクロサービスでE2Eテストが重く壊れやすくなる理由
マイクロサービス構成では、1つの機能を確認するために複数のサービスを連結して動かすE2E(エンドツーエンド)テストが増えがちです。ソフトウェア開発の実務知見をまとめるMartin Fowler氏のサイトでは、外部サービスとの通信は「異なるチームによって保守されている」「ネットワークが遅く不安定になりうる」「サービス自体の信頼性が低い可能性がある」という特性を持つと指摘されています*2。
この特性により、E2Eテストは環境構築の手間が増え、関係サービスのどこか1つが不安定になるだけでテスト全体が失敗する状態になりやすくなります。テストダブル(モック)を使えば実行は安定しますが、今度は「テストダブルへの呼び出し結果が、実際の外部サービスへの呼び出しと同じ結果を返すか」を別途確認する必要が生じます*2。
プロバイダ側が事前連絡なくAPI仕様を変更すると、依存する複数のコンシューマが同時に影響を受けます。Martin Fowler氏の別稿では、プロバイダが一方的にスキーマ変更を進めると「無関心な消費者まで影響を受ける」ケースが生じると述べられています*3。コントラクトテストは、この「隠れた結合」を契約という形で可視化し、E2Eより軽量な単体テストに近い速度で連携仕様のズレを検出する狙いを持つ手法です*3。
消費者駆動契約(CDC)の流れとPact Brokerの役割
消費者駆動契約(Consumer-Driven Contracts)とは、サービスプロバイダーが提示する契約ではなく、消費者(コンシューマ)側の期待から導出された契約を指します*3。従来型のプロバイダー中心の契約設計とは逆に、「消費者の要求がプロバイダーの契約仕様を決定する」という考え方に基づきます*3。
具体的な流れは次のとおりです。まずコンシューマ側が、自分たちが必要とするリクエストとレスポンスの組み合わせを自動テストの形で記述します。このテストを実行すると、Pactが契約ファイルを自動生成します*1。生成された契約はPact Brokerと呼ばれる共有サーバーに登録し、プロバイダ側チームがビルドパイプラインで参照できるようにします*3。プロバイダ側は、登録された契約どおりに応答できるかを自チームのテストで検証します。
Pact Brokerは、コンシューマとプロバイダの依存関係と、各バージョンがどの環境にデプロイされているかを記録します*4。この記録をもとに、新しいバージョンを本番環境へデプロイする前に「can-i-deploy」というコマンドを実行すると、Pact Brokerが保持する検証状況の一覧(公式ドキュメントでは「Pactマトリックス」と呼ばれます)を参照し、デプロイ済みの他バージョンと互換性があるかを判定します*4。デプロイ後は「record-deployment」でその環境の稼働バージョンを記録し、次回以降の判定に反映させます*4。
このCDCの仕組みにより、プロバイダ側は「実際に消費者が使っている部分」だけを優先して検証でき、無関係な項目まで網羅的にテストする必要がなくなります*1。分散環境で各サービスが独立して進化しながら、破壊的変更の影響を事前に把握できる点が、マイクロサービスでCDCが有効とされる理由です*3。
E2E・統合テストとコントラクトテストの使い分け
本節では「コントラクトテストが担う役割」、次節では「その導入を外注する際に何を準備すべきか」をペアで整理します。コントラクトテストとE2E・統合テストは代替関係ではなく、検証する対象の粒度が異なる補完関係にあります。
E2Eテストは、複数のサービスを実際に連結し、利用者の操作シナリオに沿って画面や業務フローが期待どおり動くかを確認します。関係するサービスの台数が増えるほど、環境構築や実行時間の負荷が大きくなり、Fowler氏が指摘するネットワークの不安定さや保守チームの分散という要因の影響を受けやすくなります*2。
一方でコントラクトテストは、コンシューマとプロバイダをそれぞれ独立に、実際の相手を起動せずに検証します*2。API連携部分の仕様が守られているかを早期に、かつ軽量に確認する用途に向いています。業務シナリオ全体の妥当性や画面表示の整合性まではコントラクトテストの対象外であるため、そこはE2E・統合テストが引き続き担う領域です。
| 観点 | コントラクトテスト(Pact) | E2E・統合テスト |
|---|---|---|
| 検証範囲 | コンシューマとプロバイダ間のAPI連携仕様(リクエスト・レスポンスの形式) | 複数サービスを連結した業務シナリオ・画面フロー全体 |
| 実行環境 | 相手サービスの実起動が不要。契約ファイルを介して独立に検証 | 関係する複数サービスを同時に起動する必要がある |
| 変更検出のタイミング | コンシューマ・プロバイダそれぞれのビルド時に早期検出しやすい*1 | 結合後の実行時に検出される |
| 不安定要因 | 相手サービスの状態に依存しないため再現性を確保しやすい | ネットワークや依存サービスの状態に影響されやすい*2 |
両者を組み合わせる場合、API連携の仕様確認はコントラクトテストで早期に済ませ、E2Eテストは業務シナリオの妥当性確認に絞り込む設計が、それぞれのテストの得意分野を活かす考え方といえます。
外注でコントラクトテストを導入する委託範囲と発注準備
コントラクトテスト(Pact)とは、契約の記述からPact Broker運用まで一連の仕組みを指すため、導入を内製だけで完結させるには複数の専門領域を横断する知識が要ります。コンシューマ側のテストフレームワークへのPact組み込み、プロバイダ側の検証設定、Pact Brokerの構築・運用、CI/CDパイプラインへのcan-i-deploy組み込みという4つの領域を扱う必要があり、いずれも既存の開発体制に新しい役割を追加する作業になります。
これらの設定を誤ると、契約の検証が形骸化するリスクがあります。たとえばプロバイダ側の検証を省略したままコンシューマ側だけ契約を生成しても、実装が契約どおりに応答する保証は得られません。CI/CDにcan-i-deployを組み込まずにデプロイを続けると、Pact Brokerに検証記録はあっても実際のデプロイ判定には反映されず、契約テストを導入した効果が本番環境の障害防止にはつながりません。
外注でコントラクトテスト導入を進める場合、委託範囲を発注前に次の単位で整理しておくと、要件のすり合わせがしやすくなります。第一に、対象とするAPI連携(どのコンシューマとどのプロバイダの組み合わせか)の洗い出しです。第二に、Pact Brokerを自社でホストするか、委託先の推奨する運用形態を採用するかの方針決定です。第三に、既存のCI/CDパイプラインへの組み込み範囲と、導入後の契約ファイルの保守を誰が担うかの取り決めです。
専門パートナーに委託した場合は、Pactの導入実績に基づいた設定パターンや、既存パイプラインとの統合方法の提案を受けられる点が内製との違いになります。一方で内製にこだわると、コンシューマ側・プロバイダ側それぞれのテスト設計とPact Broker運用の知識を並行して確保する負荷が続きます。委託の目的は「難しいから任せる」ことではなく、契約の検証が形骸化するリスクを避け、CI/CDに組み込んだ状態まで到達させることにあります。
まとめ:コントラクトテスト導入を外注で進める3つの判断軸
本稿では、コントラクトテスト(Pact)の仕組みと導入を外注で進める際の考え方を整理しました。要点を3つに集約すると次のとおりです。第一に、コントラクトテストはコンシューマとプロバイダの契約をもとに、E2Eより軽量にAPI連携仕様のズレを検出する手法である点です。第二に、消費者駆動契約(CDC)の流れとPact Brokerのcan-i-deploy機能が、デプロイ前の互換性判定を支える仕組みである点です。第三に、外注では対象API連携の洗い出し・Broker運用方針・CI/CD組み込み範囲を発注前に整理する必要がある点です。
よくある質問
コントラクトテストとモックを使った単体テストは何が違いますか。
モックを使った単体テストは、開発者が想定した応答をテストダブルに設定するだけで、実際のプロバイダの挙動と一致しているかは別途確認しません。コントラクトテストは、コンシューマが生成した契約をプロバイダ側が自分の実装で検証する工程を含むため、テストダブルへの呼び出し結果と実サービスの応答が一致しているかを確認できる点が異なります*2。
Pact Brokerは自社でホストする必要がありますか。
Pact Brokerはコンシューマとプロバイダの依存関係とデプロイ状況を記録する共有サーバーの役割を担うため、自社ホスト型・マネージド型のいずれかを選ぶ運用形態の判断が必要です*4。どちらを選ぶかは、既存のCI/CD基盤や運用体制に応じて発注前に方針を固めておくことが望ましいといえます。
既存のE2Eテストをすべてコントラクトテストに置き換えられますか。
コントラクトテストはコンシューマとプロバイダ間のAPI連携仕様を検証する手法であり、業務シナリオ全体や画面フローの妥当性を確認するE2Eテストとは検証範囲が異なります*2。そのため全面的な置き換えではなく、API連携部分をコントラクトテストで早期に検証し、業務シナリオの確認はE2Eテストに残す組み合わせが実務上の選択肢になります。
can-i-deployはどのタイミングで実行しますか。
can-i-deployは、新しいアプリケーションバージョンを本番環境などにデプロイする前に実行し、Pact Brokerに記録された検証状況と各環境の稼働バージョンをもとに互換性を判定します*4。デプロイ後は record-deployment でその環境の稼働バージョンを記録し、次回以降の判定に反映させます*4。
著者:テレリモ総研編集部 鈴木 亮佑
ご不明な点はお問い合わせフォームからもご連絡いただけます。
- *1 出典:Pact「What is Pact?」docs.pact.io(https://docs.pact.io/)
- *2 出典:Martin Fowler「ContractTest」martinfowler.com(https://martinfowler.com/bliki/ContractTest.html)
- *3 出典:Martin Fowler「Consumer-Driven Contracts: A Service Evolution Pattern」martinfowler.com(https://martinfowler.com/articles/consumerDrivenContracts.html)
- *4 出典:Pact「Can I Deploy?」Pact Broker docs.pact.io(https://docs.pact.io/pact_broker/can_i_deploy)