セロリ食べたい

とりあえず作りました

NLTHTTPStubServer を使って iOS アプリの通信周りのテストを書こう

テスト実行時にモックとなる Web サーバを起動して、思い通りのレスポンスを返す環境が作れる NLTHTTPStubServer というツールがある。これを使えば、web API の実行の成功・不成功などのテストが楽に書ける。テスト実行時に叩く API の URL をちょこっと書き換えるだけなので、テストのためにコードを修正する部分は少ないだろうし、実際のアプリケーションの動作とほぼ同じ状態でテストができるはずだ。

NLTHTTPStubServer の導入

NLTHTTPStubServer は以下のライブラリに依存しているので、これらをプロジェクトに追加する。

  • CocoaHTTPServer - https://github.com/robbiehanson/CocoaHTTPServer
  • CocoaAsyncSocket - CocoaHTTPServer の Vendor に入っている
  • CocoaLumberjack - CocoaHTTPServer の Vendor に入っている

NLTHTTPStubServer のソースコードは github で公開されているので、これを取得する。
https://github.com/yaakaito/NLTHTTPStubServer

NLTHTTPStubServer のソースコードをプロジェクトに追加しよう。NLTHTTPStubServer は ARC を使っていないので、ソースコードを追加したら NLTHTTPStubServer のファイル群のコンパイラフラグに -fno-objc-arc をつける。

f:id:Slightair:20120427231108p:plain

最後に以下の標準フレームワークをプロジェクトに追加すれば導入完了だ。

  • CFNetwork.framework
  • Security.framework

f:id:Slightair:20120427231123p:plain

テストを書く

NLTHTTPStubServer を使って何か簡単な API クライアントを作ってそのテストを書いてみよう。今回は coderwall (http://coderwall.com) というサイトのユーザプロフィールを取得する API クライアントを作ってみる。APIについての説明はここに書いてある。 http://coderwall.com/api

テストは GHUnit を使って書いた。
また、ネットワークライブラリは AFNetworking を使った。

以下のような感じで使えるクライアントになるといいのかな。

block でAPIの実行が成功した時と失敗した時の処理を渡してあげる感じ。

GHUnit のテストクラス CoderwallAPIClientTest を作成する。非同期のテストがしたいので GHAsyncTestCase のサブクラスとする。

テストのためにAPIの実行結果をファイルに保存した。

curl http://coderwall.com/slightair.json -o slightair.json

さらに存在しないユーザ名を指定するとステータスコード404 で 空文字列を返すようなので、API実行失敗時のテストのために空のファイル hogehogehoge.json を用意した。

テストを書くとざーっとこんな感じになった。

setUpClass メソッドではStubサーバのポート番号を指定したり、サーバのインスタンスを作って起動したりしている。今回は 12345 で Stubサーバが起動するようにしている。サーバは tearDownClass メソッドで停止する。

setUp メソッドでひとつのテストが走るたびに Stub サーバをきれいにしている。Stub サーバにはサーバに返してほしいレスポンスをテストの最初でひとつひとつ登録する仕組みになっている。ここで登録したレスポンスが全て返されるようにテストを書かないといけない。もし登録したレスポンスを返さずに残っていたらテスト失敗とみなす。tearDown メソッドでこれを監視している。

testProfileAPISuccess メソッドと testProfileAPIFailure メソッドを定義し、Profile API が成功した時と失敗した時のテストを書いた。

さっき保存した JSON ファイルから NSData クラスのインスタンスを作り、Stub サーバに Stub を追加する。これで設定したパスにリクエストがあったとき、ファイルの内容をクライアントに返すようになる。andJSONResponse メソッドで JSON のデータを指定すると Content-Type に application/json を含めてくれる。またステータスコードも指定することができる。

実装した CoderwallAPIClient は AFHTTPClient クラスのサブクラスなので、clientWithBaseURL: メソッドで Stub サーバにアクセスするように指定してあげれば、実際のアプリケーションと同じクライアントを使ってテストができる。あとは API を実行した後にすべき処理を書いていたところで、クライアントが正しく機能しているかどうかのテストを書いていけばよい。

作った coderwall の API クライアントは https://github.com/slightair/coderwallAPIClient に置いてあります。