RSpecを使ってAPIのテストを行う

最近やたらとAPIを書くことが多いので、一旦自分の整理も含め、テスト周りの基本的なところについて書こうと思いました。

## 環境
* Ruby 2.2.0
* Rails 4.2.3
* RSpec 3.3.2
* Guard
* FactoryGirl

RSpec,Guard,FactoryGirlのインストール・使い方に関しては、あらかじめ「[RailsでRspecを使用するための準備など](http://qiita.com/yu_0105/items/8d366698906972ce60b1#factorygirl%E3%81%AB%E3%82%88%E3%82%8B%E3%83%86%E3%82%B9%E3%83%88%E3%83%87%E3%83%BC%E3%82%BF%E3%81%AE%E7%94%9F%E6%88%90)」を読んで用意しておいてください。

## RspecでAPIのテストを行う
RspecでAPIのテストを行う際には、通常のControllerテストではなく、Request specという機能を使用します。
Request specでテストを行う場合は、specフォルダ以下にrequestsフォルダを作成し、その下にspecファイルを作成していきます。

### 準備

#### specファイルの作成
はじめにspecファイルを作成していきます。今回はUserというModelに関連するAPIのテストを行う前提で進めていきます。

```
~ bundle exec rails g rspec:integration User
create  spec/requests/users_spec.rb
```

#### FactoryGirlでテストデータの生成
今回はテストデータをFactoryGirlで作成してテストを行います。
spec/factoriesフォルダを作成し、user.rbを作ります。

```rb
FactoryGirl.define do
  factory :user do
    username "hoge"
    display_name "hoge fuga"
    email "hogehoge@fugafuga.com"
    password "qita"
  end
end
```

#### Guardの起動
自動でテストが実行されるようにGuardを起動しておきます。
Railsのアプリケーションディレクトリにて以下を実行しておいてください。
これでspecファイルが保存される度にテストが自動で実行されます。

```
~ bundle exec guard
```

### テストを書く
ここまでで準備は完了したので、いよいよ実際にテストを書いていきます。

#### GET /api/users/:id
はじめにこのURLのAPIが正常に動いているかどうかのテストを行います。
ちなみにこのAPIを定義しているcontrollerは以下のようになっています(簡易的に実装)。

```rb
# controller
def show
  @user = User.find_by(id: params[:id])
  render json: @user.response_format
end

# model
def response_format
  user = {
      username: self.username,
      display_name: self.display_name
  }
end
```

準備の時に作成した、users_spec.rbを開き、以下のように書いていきます。

```rb
require 'rails_helper'

RSpec.describe "Users", type: :request do
  describe "GET /api/users/:id" do
    before do
      @user = FactoryGirl.create(:user, { username: "qita_test" })
      get api_user_path(@user)
      @json = JSON.parse(response.body)
    end

    it '200が返ってくる' do
      expect(response).to be_success
      expect(response.status).to eq 200
    end

    it '取得したデータのusernameがqita_test' do
      expect(@json["username"]).to eq "qita_test"
    end
  end
end
```

これは、/api/users/:idに対してGETリクエストでアクセスした際に、
1. 正常にhttp status codeが200を返す
2. 取得したデータが指定したidのものである
ことを検証するためのテストとなります。

eqなどコード内で使われているマッチャに関しては、以下を参考に書くことが多いです。

* [使えるRSpec入門・その2「使用頻度の高いマッチャを使いこなす」](http://qiita.com/jnchito/items/2e79a1abe7cd8214caa5)

#### POST /api/users
先ほどはGETのAPIのテストを書いたので、続いてPOSTのAPIのテストを書いていきます。

```rb
describe "POST /api/users" do
  before do
    @params = FactoryGirl.attributes_for(:user)
  end

  it '200が返ってくる' do
    post api_users_path, @params
    expect(response).to be_success
    expect(response.status).to eq 200
  end

  it 'Userレコードが1増える' do
    expect { post api_users_path, @params }.to change(User, :count).by(1)
  end
end
```

これは、/api/usersに対してPOSTリクエストでアクセスした際に、
1. 正常にhttp status codeが200を返す
2. ちゃんとデータが保存され、増えている
ことを検証するためのテストとなります。

describe, context, itなどの単語で各文が始まっているかと思います。
どういう使い分け？と思った方は以下の記事を参考にしてみると良いかもしれません。

* [RSpecの(describe/context/example/it)の使い分け](http://qiita.com/uchiko/items/d34c5d1298934252f58f)


## 参考
* [RailsでAPIサーバを開発する(AngularJS, Ruby on Rails, SPA)](http://dev.classmethod.jp/server-side/spa_ruby-on-rails_api_angularjs/)
* [Rails でつくる API のテストの書き方（RSpec + FactoryGirl）](http://blog.inouetakuya.info/entry/2013/10/27/200111)
* [【Rails】rspecでAPIのテストを作成する](http://totutotu.hatenablog.com/entry/2015/03/10/%E3%80%90Rails%E3%80%91rspec%E3%81%A7API%E3%81%AE%E3%83%86%E3%82%B9%E3%83%88%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B)