WebAPIをRSpecでテストする（準備+参照API）

最近RailsでWebAPIを作成しました。リクエストを受け取り、DBからデータを引いて、レスポンスで返すという標準WebAPIですが、自動テストを作成します。このような記事はたくさんありますが、バージョンごとに差異があったり、人それぞれの標準があるので、私も書き残しておきたいと思います。まずは、今回テスト対象としたAPIを以下に示します。

#RSpecでテストするAPI
以下のように、5APIのテストを書きたいと存じます。
まず、この記事では準備と、1のAPIテストを実施します。

|NO|Method|URL|
|-----------:|:-----------|:------------|
|1|GET|http://example.com/select/|
|2|GET|http://example.com/select/id|
|3|POST|http://example.com/create/|
|4|PUT|http://example.com/update/id|
|5|DELETE|http://example.com/delete/id|

#環境整備
RSpec（+factory_girl）を動かすために、環境を整備します

**環境の確認**

```sh
$ uname -a
Linux idp 3.10.0-327.3.1.el7.x86_64

$ cat /etc/redhat-release 
CentOS Linux release 7.2.1511 (Core) 

$ ruby -v
ruby 2.3.0p0 (2015-12-25 revision 53290) [x86_64-linux]

$ rails --version
Rails 4.2.5

$ gem -v
2.5.1
```

**RSpec準備（gem追加）**
railsプロジェクト内のGemfileのテストディレにRSpecを追加する

```rb:/home/ruby/app/Gemfile
group :test do
  gem "rspec-rails"
  gem "factory_girl_rails"
end
```

**RSpec準備（インストールから、テンプレート作成）**
インストールと、テスト用テンプレート作成

```sh
#gemからインストール
$ bundle install
Installing rspec-support 3.4.1
Installing rspec-core 3.4.4
Installing rspec-expectations 3.4.0
Installing rspec-mocks 3.4.1
Installing rspec-rails 3.4.2
Installing factory_girl 4.5.0
Installing factory_girl_rails 4.6.0

#テンプレート作成
$ rails g rspec:install
      create  .rspec
      create  spec
      create  spec/spec_helper.rb
      create  spec/rails_helper.rb
```

#テストコーディングと実施
環境が整備できたので、まずはGETAPIのテストをテストします。
テスト対象のAPIを以下に示します。

**テストするAPI**
GET http://example.co.jp/select/
最新のユーザを1件取得して、jsonの形で返す

```rb:/home/ruby/app/controllers/user_controller.rb
def select
  latest_user = User.order("created_at DESC").limit(1)
  render json: latest_user,status: :ok
end
```
**テスト対象のAPIが参照しているテーブル構成**

```mysql
MariaDB [app]> desc users;
+-----------------+--------------+------+-----+---------+----------------+
| Field           | Type         | Null | Key | Default | Extra          |
+-----------------+--------------+------+-----+---------+----------------+
| id              | int(11)      | NO   | PRI | NULL    | auto_increment |
| name            | varchar(255) | YES  |     | NULL    |                |
| auth            | varchar(255) | YES  |     | NULL    |                |
| password_digest | varchar(255) | NO   |     | NULL    |                |
| mail            | varchar(255) | YES  |     | NULL    |                |
| created_at      | datetime     | NO   |     | NULL    |                |
| updated_at      | datetime     | NO   |     | NULL    |                |
+-----------------+--------------+------+-----+---------+----------------+
10 rows in set (0.00 sec)
```

**テストクラス作成**

```shell
$ rails g rspec:controller user
      create  spec/controllers/user_controller_spec.rb
```

**ファクトリを定義する**
ディレクトリ作成

```sh
$ mkdir /opt/app/spec/factories
```

ファクトリ作成

```rb:/opt/app/spec/factories/user.rb
FactoryGirl.define do
  factory :Venus, class: User do
    name     "Venus"
    auth     "1234"
    password "kinsei"
    email    "kai.kuskari@gmail.com"
  end
end
```

**テストをコーディング（修正前）**

```rb:/home/app/spec/controllers/user_controller_spec.rb
require 'rails_helper'

RSpec.describe UserController, type: :controller do

end
```

**テストをコーディング（修正後）**

```rb:/home/app/spec/controllers/user_controller_spec.rb
require 'rails_helper'

RSpec.describe UserController, type: :controller do
  describe 'GET select' do
    before do
      @user = FactoryGirl.create(:Venus)
      get "select"
    end
    it "get select" do
      expect(response).to be_success
    end
    it "json parse" do
      json = JSON.parse(response.body)
      expect(json[0]['name']).to eq @user.name
      expect(json[0]['auth']).to eq @user.auth
      expect(json[0]['mail']).to eq @user.mail
    end
  end
end
```

**テスト実行**

```sh
$ rake spec
Finished in 0.05643 seconds (files took 1.67 seconds to load)
3 examples, 0 failures, 0 pending
```

APIのテストは以上です。ファクトリで指定したユーザ情報を、テスト前に登録しておき、APIのテストで登録したユーザが引けるか確認、取得したjson文字列の各項目と付き合わせを行って、一致することを確認しています。