Rails5へのRspec導入から実行確認まで

[株式会社TECH LUCK](https://techluck.co.jp/?utm_source=qiita&utm_medium=article&utm_campaign=myarticle)という会社で代表兼エンジニアをしている齊藤です。

DXプロジェクト、開発プロジェクト、Rails開発などでお困りごとがありましたら[弊社HP](https://techluck.co.jp/?utm_source=qiita&utm_medium=article&utm_campaign=myarticle)からご相談をいただけますと幸いです。
以下のような問題に対応することが可能です。
- プロジェクトでRailsエンジニアが足りなくて困っている
- Railsのバージョンアップをしたいがノウハウ・リソースが足りなくて困っている
- オフショア開発をしているが、要件の齟齬やコード品質が悪いので改善したい

また、Railsエンジニアも募集しておりますので、興味がありましたら[弊社HP](https://techluck.co.jp/?utm_source=qiita&utm_medium=article&utm_campaign=myarticle)からご連絡いただけますと幸いです。

# 前提

2017年10月に`Factory Girl`が`Factory Bot`に名前変更になったり、`rails-controller-testing`が必要になったりとしたので、Rails5でのRsepcの導入方法をまとめておこうと思います。


# Rspecの導入
## 必要なgemのインストール
`Gemfile`を以下のように記述し`bundle install`します。

```ruby
group :development, :test do
  gem 'rspec-rails'
  gem 'factory_bot_rails'
  gem 'rails-controller-testing'
end
```

### rails-contorller-testing
`rails-controller-testing` はこれまで `rspec-rails` だけで使えていた `assigns` がRails5から、このgemをインストールしないと使えなくなりました。


### factory_bot_rails

`factory_bot_rails`は以前は`factory_girl_rails`でしたが、名前に問題？があったため変更になりました。

既存のプロジェクト`factory_girl_rails`から`factory_bot_rails`へ変更する際は、[こちらの記事を参照](https://qiita.com/jnchito/items/c71b8f66f61214227555)ください。

## rspecのインストール

rspecの必要ファイルをインストールするため、以下のコマンドを実行してください。

```bash
bundle exec rails generate rspec:install
```

以下の3つのファイルが作成されます。

```bash
.rspec
spec/spec_helper.rb
spec/rails_helper.rb
```

Factory Botの設定のために、spec/rails_helper.rbに以下を記述します。

```spec/rails_helper.rb
RSpec.configure do |config|
  # 色々な記述があるので、一番下に追記する
  config.include FactoryBot::Syntax::Methods
end
```

`rails g controller ~~~` などのコマンドでrspec用のテストファイルを作成するために、`application.rb`に以下の記述を書き加えましょう。


```application.rb
config.generators do |g|
      # 色々な記述があるので、一番下に追記する
      g.test_framework :rspec,
                       fixtures: true,
                       view_specs: false,
                       helper_specs: false,
                       routing_specs: false,
                       controller_specs: true,
                       request_specs: false
      g.fixture_replacement :factory_bot, dir: "spec/factories"
    end
```

これでRspecの導入の完了です。

## 出力結果のカスタマイズ

また、テストの実行結果を見やすくしたい方は.rspecをカスタマイズするといいでしょう。
デフォルトの出力では以下のようになっています。

```ruby
# デフォルトの出力結果
.

Finished in 0.02768 seconds (files took 3.09 seconds to load)
1 example, 0 failures
```

.rspecの記述を以下のように変更して実行すると出力結果が見やすくなります。

```ruby
--format documentation
```

```ruby
# 変更後の出力結果
TweetsController
  GET #index
    render the :index template

Finished in 0.02567 seconds (files took 2.97 seconds to load)
1 example, 0 failures
```

どこのテストが成功したのかわかりやすくなりました。
他にも色々なカスタマイズがあるので、調べみると面白いかと思います。


# 実行して確認

簡易的なTwitterのようなアプリケーションを考えましょう
ツイート情報を管理するためのTweetモデルがあるとします。
Tweetモデルは以下のような構成になっています。

```schema.rb
create_table "tweets", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
    t.string  "text"
    t.string  "title"
  end
```

`specディレクトリ` 以下に `models, controllersディレクトリ` を作成します。
これは、モデルとコントローラーの実際のrspecのテストを記述するファイルが入るディレクトリになります。
加えて、`specディレクトリ` 以下にFactory Botための `factoriesディレクトリ` を作成しましょう。

まず、`tweetモデル`のための`facotory`を作成するために、`spec/factories/tweets.rb`を作成しましょう。
また、`spec/factories/tweets.rb`を以下のように記述しましょう。

```spec/factories/tweets.rb
FactoryBot.define do
  factory :tweet do
    title 'ビール好き集まれ'
    text  '全国のビール好きのために、各国の様々なビールを集めました。'
  end
end
```

これで`tweetモデル`の`Factory`ができました。
次に、コントローラーのテストをしましょう。
`app/controllers/tweets_controller.rb`は以下のようになっています。

```app/controllers/tweets_controller.rb
class TweetsController < ApplicationController
  def index
    @tweets = Tweet.all
  end
end
```

ではテストしてみましょう。
`spec/controllers/tweets_controller_spec.rb`を作成しましょう。
また、以下の記述をしましょう。

```spec/controllers/tweets_controller_spec.rb
require 'rails_helper'

describe TweetsController, type: :controller do
  describe 'GET #index' do
    it "render the :index template" do
      get :index
      expect(response).to render_template :index
    end
  end
end
```

正常にテストが完了した場合は以下のようになります。

```bash
.

Finished in 0.03011 seconds (files took 2.76 seconds to load)
1 example, 0 failures
```

一番最初の `.`　（ドット）は成功しているという意味になります。
テストが失敗している場合は `F` となります。

ここで注意しなければならないことは、以下の通りです。
***（ここが意外とはまるところ）***

- `require 'rails_helper'`の記述を忘れないこと 
  - 記述を忘れた場合 `NameError: uninitialized constant TweetsController` というエラーがでてくる
- `describe TweetsController, type: :controller do`のTweetsControllerの部分はシングルクオート、ダブルクオードなどで囲まないこと 
  - 囲った場合 `@controller is nil: make sure you set it in your test's setup method.` というエラーがでてくる

## 参考にした記事
[Rails RSpecの基本 ~導入編~](https://qiita.com/shizuma/items/8221544601aa3d0770d2)
[spec/controllers エラー @controller is nil: make sure you set it in your test's setup method.](http://tkymtk.hatenablog.com/entry/rspec-controller-is-nil-error-2014-1)
[RSpec の Progress Bar をカスタマイズする](https://qiita.com/pekepek/items/1f725447ff25dda1f75d)