契約テストとPactについて調べたことをまとめる。
コンシューマ(サービスを呼び出す側)とプロバイダー(サービスを提供する側)の間の動作をテストするテスト手法のことである。
コンシューマーとプロバイダー間での合意を契約として記述し、その契約に基づいてテストを行う。
コンシューマーが契約を発行し、プロバイダーはその契約に従ってテストを行う形式の契約テストをコンシューマー駆動契約テストと呼ぶ。
一方で、プロバイダーが契約を発行し、コンシューマーはその契約に従ってテストを行う形式の契約テストをプロバイダー駆動契約テストと呼ぶ。
コンシューマー駆動契約テストとプロバイダー駆動契約テストのどちらが向いているかは、コンシューマーの数やAPIの安定性(変更頻度)、開発プロセスなど主導権をどちらが持ちやすいかによって異なる。
双方向契約をサポートするpactflowというサービスもある。pactflowは、コンシューマ駆動契約テストをサポートするPactをベースにしている。pactflowはpactと違ってOSSではない。
cf.
Open APIやProtoBufなどのスキーマ駆動のAPI開発が整っていれば、契約テストの必要性に疑問を感じるかもしれない。
APIスキーマはAPIの仕様を定義する文書であり、エンドポイントやリクエスト・レスポンス、データモデルなどの要素を含んでいる。
スキーマ駆動をサポートするツールを使えば、APIの定義を元にコンシューマー側とプロバイダー側のコードそれぞれ生成することができる。
APIスキーマ通りに実装がされていることについて一定の保証を得ることができても、APIの振る舞い(実装されたAPIが期待通りに動作するか)を保証することができない。
スキーマー駆動のみではプロバイダーの変更がコンシューマーに通知されることをコードファーストで担保することができないため、コミュニケーションやテストの手間が発生する。
契約テストはサービス間の動作をテストするための手法であり、APIスキーマはAPIの仕様を定義するための文書であるため、APIスキーマと契約テストは異なる目的を持っている。
cf.
コンシューマーまたはプロバイダー主導のどちらかに寄らない契約テストのメリットとデメリットについて整理する。
cf.
契約テストのためのツールで、コンシューマー駆動契約テストをサポートする。プロバイダー駆動契約テストはサポートされていない。
多言語に対応しており、テスティングフレームワークやビルドツールなどとの連携も可能になっている。
Pactでは、HTTPとメッセージ(非HTTPなメッセージキュー。Pact自体はRabbit MQやSQS、Kafkaなどの実装の詳細を把握せずにメッセージそのものをテストできるようになっている)をサポートしている。
Pactの動作フローは以下のような流れになっている。
cf.
組織がある程度の規模で、複数チームで開発しているとサービス間の整合性をどのように保つか?という課題が自然に発生すると思う。
契約テストはそのような課題に対して有効な手法であると思う。
特に、APIの仕様変更を自動で検知できるようになるのは大きなメリットだと思う。これはチームあるいはサービスが増えれば増えるほどレバレッジが効いてくるのではないかと思った。
そんなメリットを感じる契約テストではあるが、調べてみた感じではあまい流行しているような印象は受けなかった。
過去のデータであるが、Technology Radarでも積極的に採用するようなステータスではなかった。
契約テストの導入にあたっては、ツール導入が前提となり得るが、そのツールの中でもメジャーなのがPactのようであった。
Pactが流行っていないように見える理由としては、コンシューマー駆動契約テストしかサポートしていないことと、導入の旨味が大きく感じられない(E2Eなど他の代替のインテグレーションテストツールで間に合ってしまっている)ことが挙げられるのではないかと思った。実際に利用してみたわけではないので感覚でしかないし、海外では実はもっと普及しているのかもしれないが、少なくとも国内ではあまり事例は多くなかった。
Pactを拡張したPactFlowについてはまだ発展途中段階という印象を受けたが、契約テストのメリットや導入障壁を下げる良いツールになり得るのではないかと思った。
サービスがある程度の規模感になってくると複数のサービスから利用されるようなAPIを提供する基盤のようなシステムが登場することがあると思うが、コンシューマー駆動契約テストよりプロバイダー駆動契約テストの方が向いているように思われる。このようなケースの場合ではPactは最適解ではないかもしれない。