Pact-Rubyによるコントラクトテスト
コントラクトテストとは、利用者とAPI提供者の間に契約(コントラクト)を定義し、利用者提供型のコントラクトテストを可能にする。
利用者提供型のコントラストテストは、利用者がやりとりしたい機能を実装するアプローチ。利用者は、API提供者にコントラクトを提供する。
なぜコントラクトテストを使うのか
OpenAPIはAPI提供者が提供する仕様書でドキュメントの役割となる。コントラクトテストは利用者とAPI提供者の間のAPI提供者が履行すべき仕様を定義でき、検証できる。
pact-rubyの図がわかりやすい。
コントラクトテストはテストを分割できる。
pact-rubyを導入する
コントラクトテストフレームワークはPact https://docs.pact.io/ を利用する。
Rubyの場合は、Pact-Ruby https://github.com/pact-foundation/pact-ruby のため、動かしてみる。
シナリオ例
pact-rubyにあるシナリオ例を動かす。
zoo-appが利用者側、animal-serviceがAPI提供者側となる。
利用者側となるzoo-appで、rspecを実行する。
> cd example zoo-app
> bundle install
> bundle exec rspec
zoo-app/spec/pacts/zoo_app-animal_service.json
のファイルが作成される。これはAPI提供者が履行すべきコントラクトテストの仕様書となる。
API提供者側となるanimal-serviceで、pact:verifyを実行する。利用者側が作成したコントラクトに基づいてAPIが提供されているかの仕様を検証できる。
> cd example zoo-app
> bundle install
> bundle exec rake pact:verify
Verifying a pact between Zoo App and Animal Service
Given there is an alligator named Mary
a request for an alligator
with GET /alligators/Mary
returns a response which
has status code 200
has a matching body
includes headers
"Content-Type" which equals "application/json;charset=utf-8"
Given there is not an alligator named Mary
a request for an alligator
with GET /alligators/Mary
returns a response which
has status code 404
Given an error occurs retrieving an alligator
a request for an alligator
with GET /alligators/Mary
returns a response which
has status code 500
has a matching body
includes headers
"Content-Type" which equals "application/json;charset=utf-8"
3 interactions, 0 failures
補記
pact-rubyの例ではSinatraが使われているが、https://github.com/pact-foundation/pact-ruby/pull/327 の対応が誤っている?ため、修正が必要。
現状だと、Host not permitted
となる。
下記に修正をする。
# lib/pact/provider/request.rb
def headers
request_headers = {}
- request_headers.merge!('HTTP_HOST' => 'localhost') if defined?(Sinatra)
+ request_headers.merge!('HOST' => 'localhost') if defined?(Sinatra)
return request_headers if expected_request.headers.is_a?(Pact::NullExpectation)
参考
Discussion