少し前から、モバイルアプリケーションに対してHermetic testと呼ばれる類のテストタイプを実施できる環境を整え始めました。その中で、JSONで記述したHTTPレスポンスを返すだけのような、簡単なMockServerを探していました。
なければ簡単なものを作ろうとも思ったのですが、結構期待していたものがあったので、メモ。
調べたもの
あたり。他にもありましたが、ざっと見て次〜としていた。
求めたもの
- Android/iOSに特化しない、共通で使えそうなMockサーバ
- JSONのような可読性のあるテキストでテストデータ(HTTP Request & Response)を管理できる
- Stand Aloneで動作し、設定ファイルとそのMockサーバアプリが手に入れば誰でも環境を構築できる
- 複数のライブラリをダウンロードして・・・というような難しさはないほうが良いですね
- HTTPのやりとりをRecord/Playbackできる
- これがあったほうが、今回の目的においては導入への壁が低くなるので良い
やりたいこと
- テスト対象はAndrid/iOSのネイティブアプリ
- 画面ごとの境界値や同値、画面遷移の状態遷移のようなところをテストする
- apkなどを作った後、描画が期待通り行われるか、というところを主に見たい。
- Stagingサーバなどを使うと、DBをに期待するテストデータ置いたりとか必要になり気軽ではない。
- 目的はクライアントアプリの確認。テストレベルでは、結合レベルやシステムレベルに近いところ。
- 正常系以外にも、意図的にサーバ側で不具合が発生した時のクライアントの振る舞いもテストしておきたい
結果
いくつか見ましたが、目的に対してはWireMockがいちばん良さそう。使い勝手も簡単。MockServerは、おそらく基本的なところは良いのですが、JSONでの保守やPlayback/Recordの機能がWireMockのほうが都合がよかった印象。ただ、MockServerはRuby Clientなどの周辺ツールがWireMockよりも整っている模様。
MockWebServerやOCMockは、やはりAndroid/iOSにテスト用ライブラリとして組み込んで使うことが目的なので、今回の趣旨とはずれていました。ですよね〜。
WireMockメモ
以下のメモのコードは、WireMockのサイトのサンプルのコピーです。
複数の通信で状態をまたぐ一連のシナリオを作成する
多くの場合、Web APIは多少なりとも状態が関係していて、一連のHTTPリクエストの流れを想定して動作確認を行う必要があります。xxxを選んだらyyyの応答を返すが、異なるとzzzを返すとか、そういうもの。JSONの記述で、それらを記述、運用できる模様。
{
"scenarioName": "To do list",
"requiredScenarioState": "Started",
"request": {
"method": "GET",
"url": "/todo/items"
},
"response": {
"status": 200,
"body" : "<items><item>Buy milk</item></items>"
}
}
{
"scenarioName": "To do list",
"requiredScenarioState": "Started",
"newScenarioState": "Cancel newspaper item added",
"request": {
"method": "POST",
"url": "/todo/items",
"bodyPatterns": [
{ "contains": "Cancel newspaper subscription" }
]
},
"response": {
"status": 201
}
}
{
"scenarioName": "To do list",
"requiredScenarioState": "Cancel newspaper item added",
"request": {
"method": "GET",
"url": "/todo/items"
},
"response": {
"status": 200,
"body" : "<items><item>Buy milk</item><item>Cancel newspaper subscription</item></items>"
}
}
HTTPレスポンスをBad Responseにする
HTTPレスポンスを遅延させる
mappingファイルに以下のように書いておけば、例えば /delayed に対しては2000msほど遅延してレスポンスを返すことができる模様。
{
"request": {
"method": "GET",
"url": "/delayed"
},
"response": {
"status": 200,
"fixedDelayMilliseconds": 2000
}
}
例えば、複数APIを呼び、それらすべてが正常に受信できたら画面を表示するというアプリの作りの場合、特定のレスポンスだけを遅くしたいなどありますね。そんな時、サクッとそういう時のテストを実現できそう。
HTTPレスポンスを意図的にBad Responseにする
他にも、Bad responsesとして
- EMPTY_RESPONSE
- MALFORMED_RESPONSE_CHUNK
- RANDOM_DATA_THEN_CLOSE
のように、空のレスポンス、意図しない変なレスポンスなどの動作を確認することができる、プリセットが用意されている。
{
"request": {
"method": "GET",
"url": "/fault"
},
"response": {
"fault": "MALFORMED_RESPONSE_CHUNK"
}
}
これを使うと、HTTPプロトコル層までは信頼しつつ、その上のアプリケーション層が変な状態のテストができそう。そういう設定を以下の手順で生成できるスクリプトを作っておくと、リリース前のテストで有効に使えそう。
- 正常な応答をRecord
- 記録したMappingファイルを元にFault caseを適当に作成する
- ↑を読み込んだテストケースを入力としたMockServerを立てる
- モバイルアプリで接続して動作を確認
最後に
描画が絡む付近のテスト、重要なのですがそこまで手が回らないところも多いですね。できて開発者が自分たちで確認するとか。一方、ユーザからするとすごく目につくので、大事な箇所だったりします。こういうところもカバーしてきたい。
AndroidとWireMockを使っている記事を見つけたので、こちらもメモがてら。
http://joshskeen.com/mocking-webservices-with-robolectric-wiremock/