consumer driven contractsで rest api/マイクロサービスをテスト #m3tech

39
Consumer Driven Contractsで REST API/マイクロサービスをテスト Toshiaki Maki (@making) Sr. Solutions Architect @Pivotal 2016-06-08 M3 Tech Meetup

Upload: toshiaki-maki

Post on 06-Jan-2017

1.918 views

Category:

Technology


2 download

TRANSCRIPT

Page 1: Consumer Driven Contractsで REST API/マイクロサービスをテスト #m3tech

Consumer Driven ContractsでREST API/マイクロサービスをテスト

Toshiaki Maki (@making)Sr. Solutions Architect @Pivotal2016-06-08 M3 Tech Meetup

Page 2: Consumer Driven Contractsで REST API/マイクロサービスをテスト #m3tech

Who am I ?•Toshiaki Maki (@making)•https://blog.ik.am•Sr. Solutions Architect•Spring Framework enthusiast

SpringFramework

徹底⼊⾨(Coming Soon?)

パーフェクトJava EE(Coming Soon?)

Page 3: Consumer Driven Contractsで REST API/マイクロサービスをテスト #m3tech

Background

Page 4: Consumer Driven Contractsで REST API/マイクロサービスをテスト #m3tech

REST API/マイクロサービスのテストどうしてますか?

図はhttp://codearte.github.io/accurestより

Page 5: Consumer Driven Contractsで REST API/マイクロサービスをテスト #m3tech

REST API/マイクロサービスのテストどうしてますか?•全サービスをDeploy?•各サービスをMock化?•テスト書いてない!?

Page 6: Consumer Driven Contractsで REST API/マイクロサービスをテスト #m3tech

全サービスをDeploy•メリット•本番環境をシミュレートできる•サービス間が実際の通信

•デメリット•全サービスのデプロイ/DBの準備が⼤変•テストに時間がかかる•デバッグし⾟い

Page 7: Consumer Driven Contractsで REST API/マイクロサービスをテスト #m3tech

各サービスをMock化•メリット•テストが速い•環境セットアップ不要

•デメリット•意味のないスタブを作りがち•本番環境では結局エラー

図はhttp://codearte.github.io/accurestより

Page 8: Consumer Driven Contractsで REST API/マイクロサービスをテスト #m3tech

テスト書いてない

Page 9: Consumer Driven Contractsで REST API/マイクロサービスをテスト #m3tech

Team BTeam A

現実世界(とあるトイレでの会話)

😕 😗

Page 10: Consumer Driven Contractsで REST API/マイクロサービスをテスト #m3tech

Team BTeam A

現実世界(とあるトイレでの会話)

😕 😗

おたくのチームのAPI使ってテストするのに時間かかったよ〜

Page 11: Consumer Driven Contractsで REST API/マイクロサービスをテスト #m3tech

Team BTeam A

現実世界(とあるトイレでの会話)

😕 😗

おたくのチームのAPI使ってテストするのに時間かかったよ〜

お、いいね。でも、さっきAPI変え

ちゃったよ。

Page 12: Consumer Driven Contractsで REST API/マイクロサービスをテスト #m3tech

Team BTeam A

現実世界(とあるトイレでの会話)

😕 😗

おたくのチームのAPI使ってテストするのに時間かかったよ〜

お、いいね。でも、さっきAPI変え

ちゃったよ。

😡

あの💢

Page 13: Consumer Driven Contractsで REST API/マイクロサービスをテスト #m3tech

Consumer Driven Contract

Page 14: Consumer Driven Contractsで REST API/マイクロサービスをテスト #m3tech

Consumer Driven Contract (CDC)

• http://martinfowler.com/articles/consumerDrivenContracts.html•アーキテクチャレベルのTDD• "Contract"を通じて、ConsumerがProviderに期待内容を共有する•ProviderのContract違反をProvider側のテストで検出

Consumer ProviderContract

Page 15: Consumer Driven Contractsで REST API/マイクロサービスをテスト #m3tech

CDCの流れ1. Consumerは期待するリクエスト/レスポンスをContractと

して定義(DSLなどを利⽤)

2. ProviderはConsumerとContractを合意(Pull Requestなどを利⽤)

3. ProviderはContractが守られていることを⽰すテストを実施ConsumerはContractを前提にモック化してテストを実施

Page 16: Consumer Driven Contractsで REST API/マイクロサービスをテスト #m3tech

CDC⽤ライブラリ• Pact-JVM• https://github.com/DiUS/pact-jvm• Pactは多⾔語(Ruby, .NET, Go, JS, Swift, etc)に対応

• Accurest• https://github.com/Codearte/accurest• Spring MVC向け• Eureka, Spring Integration, Spring Cloud Streamにも対応している• 今後Spring Cloud Contractという名前になるかも?

Page 17: Consumer Driven Contractsで REST API/マイクロサービスをテスト #m3tech

Accurest

Page 18: Consumer Driven Contractsで REST API/マイクロサービスをテスト #m3tech

Accurest•DSLにGroovyを使⽤• Provider向けにRestAssuredとJSON Assertを使ったテストを⽣成(JUnit or Spock)• Consumer向けにWireMock⽤のスタブファイルを⽣成• Consumerのテストにスタブサーバーを組み込める 図は

http://codearte.github.io/accurestより

Page 19: Consumer Driven Contractsで REST API/マイクロサービスをテスト #m3tech

ContractDSL

Consumer Provider

期待するリクエスト/レスポンスを定義

Page 20: Consumer Driven Contractsで REST API/マイクロサービスをテスト #m3tech

ContractDSL

テストケース

スタブファイル

Consumer Provider

RestAssured + JSON Assertなコード⽣成

WireMock⽤のスタブファイルを⽣成

Page 21: Consumer Driven Contractsで REST API/マイクロサービスをテスト #m3tech

ContractDSL

テストケース

スタブファイル

Consumer Provider

RestAssured + JSON Assertなコード⽣成

WireMock⽤のスタブファイルを⽣成

Providerの破壊的な変更によるContract違反を検出可能

Page 22: Consumer Driven Contractsで REST API/マイクロサービスをテスト #m3tech

Accurest Maven Plugin

$ mvn accurest:convert

$ mvn accurest:generateTests

$ mvn accurest:run

$ mvn accurest:generateStubs

Provider向け

Consumer向け

テストコードを⽣成

WireMock形式に変換

モックサーバーを起動モックのjarを⽣成

Page 23: Consumer Driven Contractsで REST API/マイクロサービスをテスト #m3tech

io.codearte.accurest.dsl.GroovyDsl.make {request {

method 'GET'urlPath '/foos'

}response {

status 200body("""[ {

"value" : 42}, {

"value" : 100} ]""")

headers {header('Content-Type': 'application/json;charset=UTF-8')

}}}

Contract DSL

Page 24: Consumer Driven Contractsで REST API/マイクロサービスをテスト #m3tech

public class AccurestTest extends MvcTest{@Test public void validate_requestForFoos() throws Exception {

MockMvcRequestSpecification request = given();ResponseOptions response = given().spec(request).get("/foos");

assertThat(response.statusCode()).isEqualTo(200);assertThat(response.header("Content-Type"))

.isEqualTo("application/json;charset=UTF-8");

DocumentContext parsedJson = JsonPath.parse(response.getBody().asString());

assertThatJson(parsedJson).array().contains("value").isEqualTo(42);

assertThatJson(parsedJson).hasSize(2);assertThatJson(parsedJson).array().contains("value")

.isEqualTo(100);}}

テストコードを⽣成Provider側

Page 25: Consumer Driven Contractsで REST API/マイクロサービスをテスト #m3tech

public class AccurestTest extends MvcTest{@Test public void validate_requestForFoos() throws Exception {

MockMvcRequestSpecification request = given();ResponseOptions response = given().spec(request).get("/foos");

assertThat(response.statusCode()).isEqualTo(200);assertThat(response.header("Content-Type"))

.isEqualTo("application/json;charset=UTF-8");

DocumentContext parsedJson = JsonPath.parse(response.getBody().asString());

assertThatJson(parsedJson).array().contains("value").isEqualTo(42);

assertThatJson(parsedJson).hasSize(2);assertThatJson(parsedJson).array().contains("value")

.isEqualTo(100);}}

テストコードを⽣成

親クラスを指定可能

Provider側

Page 26: Consumer Driven Contractsで REST API/マイクロサービスをテスト #m3tech

public class MvcTest {@Beforepublic void setup() {

RestAssuredMockMvc.standaloneSetup(

new FooController());}

}

テストコードを⽣成Provider側

Page 27: Consumer Driven Contractsで REST API/マイクロサービスをテスト #m3tech

public class MvcTest {@Beforepublic void setup() {

RestAssuredMockMvc.standaloneSetup(

new FooController());}

}

テストコードを⽣成Provider側

MockMVCでも組み込みサーバーでも可

Page 28: Consumer Driven Contractsで REST API/マイクロサービスをテスト #m3tech

{"uuid" : "d0c6c40b-47a8-4504-967d-b470f382d820","request" : {"urlPath" : "/foos","method" : "GET"

},"response" : {"status" : 200,"body" : "[{¥"value¥":42},{¥"value¥":100}]","headers" : {

"Content-Type" : "application/json;charset=UTF-8"}

}}

WireMock形式に変換Consumer側

Page 29: Consumer Driven Contractsで REST API/マイクロサービスをテスト #m3tech

$ mvn accurest:convert accurest:run

Consumer側

Page 30: Consumer Driven Contractsで REST API/マイクロサービスをテスト #m3tech

$ mvn accurest:generateStubs install or deploy

Consumer側

myprovider-0.0.1-SNAPSHOT-stubs.jarがMavenレポジトリにデプロイされる

Page 31: Consumer Driven Contractsで REST API/マイクロサービスをテスト #m3tech

Consumer側

Consumer

Provider/foos /foos

{...}Got "{...}"

テストしたい

Page 32: Consumer Driven Contractsで REST API/マイクロサービスをテスト #m3tech

classifier

Consumer側

stubrunner.stubs.ids=com.example:myprovider:+:stubs:9999

src/test/resources/application.properties

groupId artifactId version

port

Page 33: Consumer Driven Contractsで REST API/マイクロサービスをテスト #m3tech

Consumer側

Consumer

Provider/foos /foos

{...}Got "{...}"

通常の組み込みサーバーテスト

WireMockのスタブサーバー

Page 34: Consumer Driven Contractsで REST API/マイクロサービスをテスト #m3tech

Consumer側

Consumer

Provider/foos /foos

{...}Got "{...}"

通常の組み込みサーバーテスト

WireMockのスタブサーバー

Consumerだけでテストできる🍺

Page 35: Consumer Driven Contractsで REST API/マイクロサービスをテスト #m3tech

DEMOhttps://github.com/making/microservices-accurest

Page 36: Consumer Driven Contractsで REST API/マイクロサービスをテスト #m3tech

CDCのメリット•クライアントが求めているリクエスト/レスポンスを知れる• Contractに違反があれば(APIの互換性が崩れたら)テストが失敗する•テストが⾃動⽣成されるためメンテナンスしやすい•新しいAPIが追加されればすぐにモックサーバーに反映できる

Page 37: Consumer Driven Contractsで REST API/マイクロサービスをテスト #m3tech

CDC(Accurest)のデメリット• Consumer側のテストが、 WireMock起動のため重くなりやすい→テストがちょっと億劫に•まだ開発途上で、時々⽣成されたコードが壊れている→issueをあげよう

Page 38: Consumer Driven Contractsで REST API/マイクロサービスをテスト #m3tech

References• Consumer Driven Contractsについて• http://martinfowler.com/articles/consumerDrivenContracts.html• http://www.slideshare.net/MarcinGrzejszczak/stick-to-the-rules-consumer-driven-contracts-201507-confitura• http://toomuchcoding.com/blog/2016/04/30/accurest-and-stub-runner-1-dot-1-0-dot-m3/

• CDC⽤ライブラリ• http://codearte.github.io/accurest/

•サンプル• https://github.com/making/microservices-accurest• https://github.com/Codearte/accurest-samples

Page 39: Consumer Driven Contractsで REST API/マイクロサービスをテスト #m3tech

Announcehttp://pivotal-japan.connpass.com

Pivotal Japan Technical Meetup2016/06/29(Wed) 18:30-