[Rails] Rspec基礎 factory_bot〜request spec

Rspecについて勉強したときのメモです。
今回はrequest specについて！
#request specとは？

リクエストスペックはコントローラのテストのこと。
リクエストに対するレスポンスを確認することをテストします。

# 実装
テストの基本の流れは、
①確認したいことを決める
②ダミーデータを作成する
③ダミーデータで①の確認したいことが起こるかどうかを確認する
です。

これをrequest specに当てはめると、
①Getなどのリクエストを送って200や正しいレスポンスが返ってくるかを確認したい
②実際にリクエストを送る
③200ステータス、レスポンスの確認
という感じです。

では流れが分かったのでコードベースでやっていきます。
今回テストするサンプルアプリは前回のmodel spec同様`User`が`title`と`content`カラムを持つ`Article`モデルを投稿できるシンプルなものです。

## factory_bot
factory_botでダミーデータを用意します。

```ruby:Gemfile
gem 'factory_bot_rails'
```

```ruby:ターミナル 
bundle install
```

```ruby:spec/rails_helper.rb
config.include FactoryBot::Syntax::Methods
```
これでインストールと設定完了。

ダミーデータを記述するフォルダとファイルを用意し、

```ruby:ターミナル 
mkdir spec/factories
touch spec/factories/users.rb
touch spec/factories/articles.rb

```
ここにダミーデータを書きます。

用意したいダミーデータは`User`モデルのデータと`Article`モデルのデータです。
記述の仕方は以下のとおり
`faker`を使ってるので簡潔にかけます！

```ruby:spec/factories/users.rb
FactoryBot.define do
  factory :user do
    email { Faker::Internet.email }
    password { 'password' }
  end
end
```

```ruby:spec/factories/articles.rb
FactoryBot.define do
  factory :article do
    title { Faker::Lorem.characters(number: 10) }
    content { Faker::Lorem.characters(number: 50) }
  end
end
```

これでダミーデータの準備完了。


## Getリクエスト
それではテストしていきます。

今回テストするのはコントローラーのこの部分。

```ruby:app/controller/articles_controller.rb
def index
 @articles = Article.all
end
```

テストファイルを作成。

```ruby:ターミナル 
rails g rspec:request article
```

以下のファイルが出来てたらOK。

```ruby:requests/articles_spec.rb
require 'rails_helper'

RSpec.describe 'Articles', type: :request do
  describe 'GET /articles' do
    it '200ステータスが返ってくる' do
      get articles_path
      expect(response).to have_http_status(200)
    end
  end
end
```
今回のgetリクエストでテストしたいことはindex actionをしたときにhttpステータスのレスポンスが正しい値(200)として返ってくるのかです。
なのでダミーデータとして必要なのは`User`と複数の`Article`ですね。
factory_botでは`create_list`を使うことでダミーデータを複数作ることができます。
ダミーデータを記述します。

```ruby:requests/articles_spec.rb
RSpec.describe 'Articles', type: :request do
  let!(:user) { create(:user) }
  let!(:articles) { create_list(:article, 3, user: user) }

  describe 'GET /articles' do
    it '200ステータスが返ってくる' do
      get articles_path
      expect(response).to have_http_status(200)
    end
  end
```
あとはターミナルでテストが通るか確認してテストが通ればOK。

```ruby:ターミナル 
bundle exec rspec spec/requests/article_spec.rb

.

Finished in 0.01966 seconds (files took 1.02 seconds to load)
1 example, 0 failures

```

無事成功

## Postリクエスト
次は同じPostリクエストです。
テストするコントローラーは以下の部分

```ruby:app/controller/articles_controller.rb
 def create
    @article = current_user.articles.build(article_params)
    if @article.save
      redirect_to article_path(@article), notice: '保存できました'
    else
      flash.now[:error] = '保存に失敗しました'
      render :new
    end
  end

```

ここでテストすることは、記事が正しく保存されるかです。
とりあえず実装した部分

```ruby:requests/articles_spec.rb
describe 'POST /articles' do
  before do
    sign_in user
   end

  it '記事が保存される' do
    article_params = attributes_for(:article)
    post articles_path({article: article_params})
    expect(response).to have_http_status(302)
    expect(Article.last.title).to eq(article_params[:title])
    expect(Article.last.content.body.to_plain_text).to eq(article_params[:content])
  end
end
```

###解説
記事を保存できるのは`current_user`だけなのでテストの前にログインしていることを`bofore`で定義しています。

```ruby
context 'ログインしている場合' do
  before do
    sign_in user
  end
end
```

postするためには記事をパラメーターで渡すので、
factory_botで用意されている`attributes_for`というメソッドを使えば記事のデータをパラメータにすることができます。

```ruby
article_params = attributes_for(:article)
post articles_path({article: article_params})
```

記事保存後にリダイレクトしているので返ってくるhttpステータスは302
保存された`title`と`content`の値がパラメーターの値と一致していれば正しく保存されていることを確認できる。

```ruby
 expect(response).to have_http_status(302)
 expect(Article.last.title).to eq(article_params[:title])
 expect(Article.last.content).to eq(article_params[:content])
```

これでテスト実行

```ruby:ターミナル 
bundle exec rspec spec/requests/article_spec.rb

.

Finished in 0.72662 seconds (files took 1.02 seconds to load)
1 example, 0 failures

```

通ればOK

以上です。