CDC testing とは
CDCとはConsumer-Driven Contract testing (CDC testing) の事で、従来スタブやVCRを用いて行ってきた外部APIのテストを大きく変えるものです。
APIが更新されると、APIを利用しているサービスの開発チームに多大なる影響が発生します。昨今はマイクロサービスアーキテクチャとして、多くのサービスを分離するような設計が多くなってきました。これもまた影響の深刻化が増している要因となっています。
APIを利用しているプロダクトの開発チームは個々にスタブを用意してCIを回しているのでAPIに破壊的変更が発生すると該当箇所を洗い出してスタブを作り直す必要があります。また、(バグ、設計ミスなどによる)意図しない破壊的変更だった場合、APIを提供している側はそれをシステム的に検知する術がありません。
E2Eというテスト手法もありますが、環境用意が大変で(テストデータの用意や冪等性を保証するための仕組み作りなど)、よく「何も変更を加えてないのにテストが落ちた」という事態がになります。またテスト時間も相当かかり深夜に走らせて早朝失敗していることを確認するパターンに陥りやすいです。
そこで今回のタイトルでもあるCDC testing (Consumer-Driven Contract testing)に着目してみます。
CDC testing では、API利用側が期待しているAPIの動きを書いておいて、APIを提供している側に「期待する振る舞いのデータ」渡します。API提供側では渡された「期待する振る舞いのデータ」を満たしていることを検証することで破壊的変更が無いことを確認できます。
CDC testingを実装したPactというフレームワークがあるので、今回はこちらを使用して実際に動きを確認してみます。
Pact とは
PactとはCDC testing を実現するためのツールです。pact-foundationが様々な言語のフレームワークを用意しています。
https://github.com/pact-foundation
javaを使いたかったので調べてみると、pact-foundationには無さそう。。ただ以下を発見しました。
https://github.com/DiUS/pact-jvm
こちらを使えばjavaでも実行できそうです。
更に、以下にかなり分かりやすいサンプルを見つけました。
https://github.com/azusa/pact-jvm-example
今回はこちらを参考にしてPactについて学びたいと思います。
CDCで使われる用語について
Provider・・・いわゆるAPIを提供する側
Consumer・・・いわゆるAPIを利用する側
Contract・・・Providerの提供するAPIに期待する振る舞いを記述したもの。Consumerが執筆する。JSON形式になるためProviderとConsumerが別言語であっても問題無いようになっている。
Pact-jvmの流れについて
- Consumer側のでContract(テスト)を記述しておきます。
(src/test/java/jp/fieldnotes/jjug/pact/provider/pact/consumer/AnimalServiceClientTest.java)
これにはリクエスト内容とレスポンス、期待する副作用を記述します。
target/pact/test_consumer-test_provider.json にファイルが配置されます。 - Consumer はテスト実行時にモックサーバーを起動し、モックサーバーに向けてリクエストを発行します。
モックサーバーは記述された Contract を元にレスポンスを返します。 - テスト完了後にConsumerはJSON形式のContractファイルを書き出します。
これをpact_brokerと呼ばれるサーバーにアップロードします。(今回の例では用意されていません。) - Providerはpact_brokerからConsumerがアップロードしたJSON形式のContractをダウンロードし、Contract通りの振る舞いを行っているかをテストします。
今回のサンプルではpact_borkerは用意されていませんが、Provider側のテストでConsumerが作成したContractを参照するように記述されています。
1234@RunWith(PactRunner.class)@Provider("test_provider")@PactFolder("../pact-jvm-example-consumer/target/pacts")public class AnimalContractTest {
感想
いかがでしたでしょうか。
正直導入コストはそこそこ大きいと思いましたが、一度CIツールに設定して開発フローに組み込めるとかなり強力なものかと思います。よほど人数が少ないスタートアップでもない限り、プロダクト別にチームメンバ(または部署)が別れていて、APIのインタフェースの変更に関してかなりのコミュニケーションコストがかかっていると思います。Pactの導入はそういったコストを削減し、より早く安全な新機能のリリースを実現できるのではないかなと思いました。
参考
使用した画像