Request SpecでDeviseのsing_in userを実施する

# Request specでDeviseのsign_inを実施する
検索するとModuleを利用したものや、認証用モデル作成としてFactory-girlを利用したやや複雑かつやや古いものが多く、少し困ったため
Rails6環境での実施を記録します。

### 実施環境
- Rails 6.0.2.2
- Factory-bot-rails 5.1.1
- Devise 4.7.1  
- RSpec 3.9

下記を実施して、devise用ユーザーとpostモデルを作成しておきます。

```
rails generate devise user
rails generate scaffold post body:string
```

migrateも忘れずに

```
rails db:migrate
```

#### spec実施時に、Deviseのhelperを呼び出せるように設定

```spec/rails_helper.rb
RSpec.configure do |config|
  #色々書いてある下に下記行を追記
  config.include Devise::Test::IntegrationHelpers, type: :request
end
```

specからrails_helperを通してDeviseの*sigin_in*等のヘルパー機能を呼び出せるようになります。

#### posts_controllerの設定
```app/controller/posts_controller.rb
class PostsController < ApplicationController
  自動生成されたbefore_actionがありますが、今回は下記のように修正
  before_action :authenticate_user!, expect: [:index]
#省略
end
```

```app/config/routes.rb
Rails.application.routes.draw do
  devise_for :users #先頭にくるようにしてください
  resources :posts
  # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
end
```

#### 認証処理なしで一度spec(自動生成されています）を実行
```
rspec spec/requests/posts_spec.rb
```

```
Failures:

  1) Posts GET /posts works! (now write some real specs)
     Failure/Error: expect(response).to have_http_status(200)
       expected the response to have status code 200 but it was 302
     # ./spec/requests/posts_spec.rb:7:in `block (3 levels) in <main>'

Finished in 0.19729 seconds (files took 3.08 seconds to load)
1 examples, 1 failure

Failed examples:

rspec ./spec/requests/posts_spec.rb:5 # Posts GET /posts works! (now write some real specs)

```

失敗の内容から、レスポンスステータス200を期待した結果302(ログイン画面へのredirect)が返却され失敗となっています。

### factory_Bot未使用の簡易な実装
spec実施時に認証用モデルを都度作成することで、簡易に実現できます。

``` spec/requests/posts_spec.rb
require 'rails_helper'

RSpec.describe "Posts", type: :request do
  describe "GET /posts" do
    before do
      #認証ユーザーを作成します。
      #各変数の中身は何でも良いです。passwordとpassword_confirmationが一致することだけ確認してください。
      @user = User.create(email: 'test@test.com', password: "password", password_confirmation: "password")
    end

    it "works! (now write some real specs)" do
      #認証処理を行います
      sign_in @user
      get posts_path
      expect(response).to have_http_status(200)
    end
  end
end

```
非常に簡易ですが、これだけでDevise認証を必要とするspecの作成は可能です。

実行結果

```
Finished in 0.12959 seconds (files took 1.07 seconds to load)
1 example, 0 failures
```

### factory_botを利用したDevise認証
fixturesのデファクトであるfactory_bot(旧factory_girl)を利用した実装です。

#### factory_bot利用できるように設定
spec配下にsupportディレクトリを作成し下記のファイルを作成

```spec/support/factory_bot.rb
RSpec.configure do |config|
  config.include FactoryBot::Syntax::Methods
end
```
併せて、下記ファイルのコメントアウトを削除し有効にします。

```spec/rails_helper.rb
Dir[Rails.root.join('spec', 'support', '**', '*.rb')].each { |f| require f }
```

テスト用modelを作成します。

```spec/factories/users.rb
FactoryBot.define do
  factory :user do
   email { "test@test.com"}
   #下記の値は同じになるようにしてください
   password { "password" }
   password_confirmation { "password"}
  end
end
```
specでfactoryを利用して認証ユーザーを取り出すようにします。

```spec/requests/posts_spec.rb
require 'rails_helper'

RSpec.describe "Posts", type: :request do
  describe "GET /posts" do
    before do
      #factory_botを利用して認証モデルを作成します。
      @user = create(:user)
    end

    it "works! (now write some real specs)" do
      #認証処理を行います
      sign_in @user
      get posts_path
      expect(response).to have_http_status(200)
    end
  end
end
```

実行結果

```
Finished in 0.11056 seconds (files took 1.28 seconds to load)
1 example, 0 failures
```

### サンプルコード
各verのサンプルコードはgithubへ上げてありますのでご参考までに。
[factory_bot未使用](https://github.com/Hyuga-Tsukui/devise-for-rspec-sample/tree/v1.0)
[factory_bot利用](https://github.com/Hyuga-Tsukui/devise-for-rspec-sample/tree/v1.1)