Marcin Grzejszczak氏はPivotalのソフトウェアエンジニアである。彼はさまざまなオープンソースプロジェクトにコントリビュートし、またMockito Cookbookの著者である。現在彼はSpring Cloud Contractの開発に取り組んでいる。これはJavaのコンシューマ駆動契約フレームワークである。InfoQはフレームワークの利点のいくつか、とくにコンシューマ駆動契約がマイクロサービスのテストをどのように手助けできるのかを話し合うためにMarcin氏にインタビューした。
要点
- コンシューマ駆動契約はアーキテクチャに対するテスト駆動開発のようなものだ。
- Spring Cloud ContractはSpringのエコシステムにうまく連携する。
- エンドツーエンドテストはコンシューマ駆動契約を使うとき余剰となることがある。
- Spring Rest DocsはSpring Cloud ContractにあるGroovy DSLの代替として使うことができる。
- 将来Spring Cloud Contractは非Javaユーザに改善したツールを提供するだろう。
InfoQ「コンシューマ駆動契約パターンの概要を教えてもらえますか?そしてマイクロサービス開発においてそれはどんな種類の問題を解決するのか説明してもらえますか?」
Marcin Grzejszczak氏「コンシューマ駆動契約はユーザが彼らのソフトウェアをテストしよりよいアーキテクチャ設計を作る手助けをすることを目指すプロセスです。私たちはそれをアーキテクチャレベルまで進歩させたテスト駆動開発と呼んでいます。今日のソフトウェアは顧客の需要や法律の変更、ビジネス要求などに対してとても早い反応を要求します。一方私たち、IT業界としてはテストされバグがない信頼性のあるソフトウェアをできるだけ早く提供したいものです。これがデプロイメントパイプラインを私たちが作った理由です。こうしたリリースとテストプロセスを自動化するためです。マイクロサービスでは、アーキテクチャスタイルの性質のために問題は増幅されています。私たちはテストプロセスへの影響なくモノリスをマイクロサービスに分解することはできません。
モノリシックな構造にある複雑性はアーキテクチャレベルまで押し付けられています。コンシューマ駆動契約はチーム間のコミュニケーションに明確ないくつかの境界線を定義しようと試みます。CDCの全体フローはコンシューマがAPI/メッセージで見えるべきものへの彼らの期待を定義するようなものです。これらの期待は契約と呼ばれます。これらの契約から後にコンシューマチームがビルドプロセス間に再利用できるスタブが生成されます。契約はまたプロデューサ側での検証を必要とします。これはプロデューサとコンシューマ双方のテストへフェイスファストなアプローチを導入することを導きます。これは本番をデバッグすることによって見つけ出すのではなくフェイルファストによってソフトウェアのビルドに失敗することを意味します(たとえばREST/AMQPメッセージにおいて誤字をしてしまうなど)。
コンシューマ駆動契約はAPI設計をそれを使う人たちへ移します。一般的にサーバサイドチームがAPIが見えるものを単に公開します。コンシューマの数が原因で、これが唯一の可能な手段となることもあります。しかしつねにそういうケースではありません。私はAPIを一般公開しない企業を見てきました。チームはAPIが見えるべきものについて協力したがりません。CDCはAPIの変更を推進するコンシューマがいるところへのアプローチを変えようと試みます。考えてみれば、これは本当に意味があることです。APIを利用するのはサーバサイドチームではありません。作成したAPIが可能な限りコンシューマに適合するべきである理由は、コンシューマがそれを使うからです。」
InfoQ「Spring Cloud Contractへのモチベーションは何ですか?なぜほかのコンシューマ駆動契約のフレームワークではなくそれを使うのですか?」
Grzejszczak氏「Devskiller社のJakub Kubrynski氏といっしょに、私たちはCDCフレームワークを分析しました。それらは高い学習曲線を持ち、とても冗長であるという結論に至りました。このようにしてAccurestは2014年12月に誕生しました。Spring Cloud Contractの前身です。契約を定義するための静的な型付きGroovy DSLを導入することを決めました。そしてここがSpring Cloud Contractと他のCDCフレームワークの主な違いとなりました。契約からSpring Cloud Contractはスタブだけでなくテストも生成します。これが意味することは、開発者が必要なことは契約を定義することだけだということです。残りはプロデューサのために自動的に生成されます。生成したスタブが信頼されることを前提とすることはCDCのまさに本質であるので、これは私たちが行いたかったとても重要な決定でした。もし契約にエンドポイント`
/foo
`存在しGET
メソッドでアクセスできると定義したなら、私たちはプロデューサ側のテストを生成します。それはGET
リクエストを`/foo
`エンドポイントに送るものです。もしそのようなエンドポイントがなかったら、テストは失敗しスタブはまったく生成されません。」Spring Cloud Contractは明らかにSpring環境とうまく連携します。Spring IntegrationやSpring Cloud Stream、Spring AMQP、Apache Camelを使ってメッセージを送るサポートがあります。しかし、Spring Cloud Contractを魅力的なオプションにしているものはStub Runnerと呼ばれるコンポーネントです。すでに契約からスタブが生成されることには触れました。デフォルトではユーザがプロデューサのスタブと契約をJARファイル形式でMavenリポジトリに公開することを期待しています。スタブがグループID"org.springframework"とアーティファクトID"spring-boot-application"を持っていると仮定しましょう。スタブを実行するには、コンシューマは次のアノテーションを付けたテストを作ります。
@AutoConfigureStubRunner (ids={'org.springframework:spring-boot-application:+'}
です。何が起こっているかというと、フレームワークが自動的にスタブがある"org.springframework:spring-boot-application"のJARの最新バージョンをダウンロードし、インメモリのHTTPサーバをランダムなポートで与えられたスタブとともに起動します。これが意味することは、アノテーション1つでビルドのための環境全体をスタブすることができるということです。また本当に興味深いこととして、Spring Cloud Contractはサービスディスカバリのツールも完全にスタブできるということです。これが意味することは、スタブはインメモリバージョンのサービスディスカバリに登録されるということです。このように本物のHTTPリクエストをあたかもサービスディスカバリを使っているかのように本物のHTTPサーバに送ることができます。
もしテスト環境でパッケージしたアプリケーションのスモークテストのいくつかを実行したくないなら、Spring Cloud Contract Stub Runnerがまたとても役立ちます。ダウンロードされたスタブは本物のサービスディスカバリのツール(たとえばEureka)に登録されます。そして契約に定義した本物のメッセージが本物のキュー(たとえばRabbitMQ)に送られます。このようにアプリケーションはスタブと話していることさえ知らない、ということになります。」
InfoQ「もしあるとするなら、コンシューマ駆動契約パターンはエンドツーエンドテストにどんなインパクトがありますか?」
Grzejszczak氏「とてもよい質問です。先ほど申したとおり、マイクロサービスを使うとアプリケーションのテストとデプロイはより複雑になります。とくに、デプロイとエンドツーエンドのテストの組み合わせは興味深いです。システムが50のマイクロサービスで構成されている仮定しましょう。次の質問に答えてみてください。
- すべてのチームがすべてのマイクロサービスのビルドやデプロイ環境を持つべきか?
- 50の環境への支払いは誰がするのか?
- もしマイクロサービスごとの環境を持たないと決定したら、デプロイキューはどのように扱うのか?もしエンドツーエンドテストの実行に長時間かかるなら、自分の順番を長時間待たなければならない...
- これらの環境は本番バージョンでデプロイされた49の他のマイクロサービスから構成されるべきか、それとも開発バージョンか?もしくは時には本番と開発どちらのバージョンでもテストを実行すべきか?
- 誰がこれらの環境を構築し、維持するのか?
- 時には企業はテスト環境で本番データを持つことができない。誰がデータをマスクしデータの完全性を考慮するのか?
またもう1つ考えるべき点があります。エンドツーエンドテストは極めてもろいということです。コード中のバグには関係しない多くの理由によりテストが失敗します。私はエンドツーエンドテストに価値がないとは言っていません。まったく逆です。しかし、いくつかの複雑な点で、コスト対利益を計算しなければなりません。コンシューマ駆動契約は救いとなります。契約のテストを実行すると、コミュニケーションが契約を破っていたときとても早い段階でビルドを壊してくれます。言い換えると、もしメッセージに誤字があったら、ビルドの始めの1分で失敗してくれたほうがよいです。2時間のエンドツーエンドテストの最後の1分でそうなるよりも。
これは議論の余地があるかもしれまんが、個人的に私は正しくすればエンドツーエンドテストは冗長で、完全に除去できると考えています。このための条件は、1) 契約テストをすること 2) 鍵となるパフォーマンスの指標を監視し警告を出すこと 3) ロールバックテストとそれをデプロイメントパイプラインに組み入れることです。このようなデプロイメントパイプラインの例としてSpring Cloud Pipelinesプロジェクトをチェックアウトできます。」
InfoQ「Spring Rest Docsとの新しい連携について教えてください。そしてそれが従来のコンシューマ駆動契約のワークフローを変えるかもしれないかどうかを教えてください。」
Grzejszczak氏「新しくはありませんが、たしかにより魅力的にしてくれるものです。Groovy DSLを書くことが好きではなく、テストを生成したくないユーザもいます。彼らはテストプロセスを完全に所有したいのです。他にもすでにSpring Rest Docsをコードのテストに使っているユーザもいます。Dave Syer氏はそうしたユーザの1人で、Spring Rest DocsにSpring Cloud Contract連携を追加したのは彼のアイデアです。このおかげでWebアプリケーションへのテストを書くことができます。また自動的にスタブを作成できます。Spring Cloud Contractの最新バージョンで、Spring Rest DocsからGroovy DSL契約を生成することもできます。
ワークフローに関しては、コンシューマがプロデューサとペアになってコンシューマの必要性を満たすテストとスタブを開発することが想像できます。 このようにプロセスは続けられます。一方Spring Rest Docsのアプローチは"プロデューサ契約"アプローチでより頻繁に使われると何かが私に伝えてきます。プロデューサが契約がどのように見えるかを定義するところです。Springでは私たちは自分で製品を試すのが好きです。Spring Initilizr(start.spring.ioの背後にあるコード)はすでにSpring Cloud Contractを使っており、Spring InitilizrのスタブはSpringのMavenリポジトリで公開されています。」
InfoQ「最後に、ロードマップで控えている何か興味深いものについて話していただけますか?」
Grzejszczak氏「ちょうどSpring Cloud Contractの新しいバージョン"1.1.0.RELEASE"をリリースしたばかりです。これにはとても興味深い機能がいくつかあります。たとえば完全なモジュール化(現在みなさんでSpring Cloud Contractの独自のパーツを提供することができます。たとえばPHPテストを生成するようなものです)があります。今後数週間はAPIを安定させバグを修正する作業となるでしょう。長期間の計画では、非Javaユーザが簡単に使えるようにすることを考えています。しかし、私たちにとってもっとも重要なことはユーザからのフィードバックであることは明らかです。ユーザのニーズを満たすために計画を調整していくでしょう。
プロジェクトについてもっと知りたい場合はホームページを確認してください。質問があればGitterで私を見つけてもらうかTwitterで@mgrzejszczakまでご連絡ください。」
Rate this Article
- Editor Review
- Chief Editor Action