【Rails】Rspecで、deviseのsingn_inを使ってログイン処理を書く

#目標
requestテストで、deviseのヘルパーを使ってログイン処理を書けるようにする

#前提
* 既にRspecでテストを１件以上実行できる <br>
ログイン処理どうすればいいの？が、メインテーマなのでRspec導入部分などは割愛します。

#本題の前に
まず、私はRspecで、model, system, requestの大きく３つに分けてテストを記述しました。その中で、systemテストでのログイン処理をどうしたのかを簡単に書いていきます。

#systemテスト
systemテストでは、機能のテストを記述しました（ボタン押したら期待通りの結果になるかとか）。この時のログイン処理は、ヘルパーメソッドを定義して使いました。<br>
導入方法は下記の記事を参考にしました。
[【Rails】Rspecでマクロを定義して処理を共通化する方法](https://qiita.com/matsubishi5/items/6df9f14e5daa5e0dc1c8)
<br>
で、結果が以下の通りです。<br>

```ruby:spec/support/helper_macros.rb
module HelperMacros

  def login(user)
    #ログインページに遷移
    visit new_user_session_path
    #入力フォームに情報を入力
    fill_in 'user[email]', with: user.email
    fill_in 'user[password]', with: user.password
    click_button 'サインインする'
  end

end
```
といった具合に、実際にログインする手順を記載することでログイン処理が完成します。<br>

```ruby:spec/system/users_spec.rb
.....

  describe "ユーザー編集ページ" do
    before do
      #ここで定義したヘルパーを使える
      login(user)
      visit edit_user_path(user)
    end

    context "ページレイアウト" do
      it "自分の編集ページに退会ボタンが存在すること" do
        expect(page).to have_link "退会する"
      end
    end
  end
.....
```
これで、ログイン処理が書けました。

#deviseのヘルパーを使ってログイン処理を書く
やっと本題です。<br>
ここで、自分がつまずいたところをちょっとお話します。なぜ、上記のログイン処理の説明をしたのかに繋がるのですが、`request`テストだと上記のヘルパーが使えません。<br>
実際に、requestテストで`login(user)`を使ってみると、`visit`ってなんですか？みたいなエラーが返されますと思います。requestテストでは、systemテストで使えた、visitというヘルパーが使えないんですね。
そこで、deviseのヘルパーを使ってログイン処理を書こうとなったわけです。

##requestテストでのログイン処理
設定は簡単です。`rails_helper.rb`にちょっと追記するだけです。

```ruby:spec/rails_helper.rb
# This file is copied to spec/ when you run 'rails generate rspec:install'
require 'spec_helper'
require 'devise'　#追記
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../config/environment', __dir__)
# Prevent database truncation if the environment is production
abort("The Rails environment is running in production mode!") if Rails.env.production?
require 'rspec/rails'
# Add additional requires below this line. Rails is not loaded until this point!

# Requires supporting ruby files with custom matchers and macros, etc, in
# spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are
# run as spec files by default. This means that files in spec/support that end
# in _spec.rb will both be required and run as specs, causing the specs to be
# run twice. It is recommended that you do not name files matching this glob to
# end with _spec.rb. You can configure this pattern with the --pattern
# option on the command line or in ~/.rspec, .rspec or `.rspec-local`.
#
# The following line is provided for convenience purposes. It has the downside
# of increasing the boot-up time by auto-requiring all files in the support
# directory. Alternatively, in the individual `*_spec.rb` files, manually
# require only the support files necessary.
#
Dir[Rails.root.join('spec', 'support', '**', '*.rb')].sort.each { |f| require f }

# Checks for pending migrations and applies them before tests are run.
# If you are not using ActiveRecord, you can remove these lines.
begin
  ActiveRecord::Migration.maintain_test_schema!
rescue ActiveRecord::PendingMigrationError => e
  puts e.to_s.strip
  exit 1
end
RSpec.configure do |config|
  # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
  config.fixture_path = "#{::Rails.root}/spec/fixtures"

  # If you're not using ActiveRecord, or you'd prefer not to run each of your
  # examples within a transaction, remove the following line or assign false
  # instead of true.
  config.use_transactional_fixtures = true

  # You can uncomment this line to turn off ActiveRecord support entirely.
  # config.use_active_record = false

  # RSpec Rails can automatically mix in different behaviours to your tests
  # based on their file location, for example enabling you to call `get` and
  # `post` in specs under `spec/controllers`.
  #
  # You can disable this behaviour by removing the line below, and instead
  # explicitly tag your specs with their type, e.g.:
  #
  #     RSpec.describe UsersController, type: :controller do
  #       # ...
  #     end
  #
  # The different available types are documented in the features, such as in
  # https://relishapp.com/rspec/rspec-rails/docs
  config.infer_spec_type_from_file_location!

  # Filter lines from Rails gems in backtraces.
  config.filter_rails_from_backtrace!
  # arbitrary gems may also be filtered via:
  # config.filter_gems_from_backtrace("gem name")
  config.include FactoryBot::Syntax::Methods
  config.include HelperMacros
  config.include Devise::Test::IntegrationHelpers, type: :request #追記
end
```
`require 'devise'`
`config.include Devise::Test::IntegrationHelpers, type: :request`
を追記します。

```ruby:spec/requests/users_logout_spec.rb
#rails_helperの読み込み
require "rails_helper"

RSpec.describe "ログアウト", type: :request do
  let!(:user) { create(:user) }

  before do
    #sign_in メソッドを使えるようになった
    sign_in user
  end

  it "ログアウトができること" do
    delete destroy_user_session_path(user)
    expect(response).to have_http_status(204)
  end

end
```

他の方の、Rspecでdeviseの機能を使えるようにする内容の記事等を参考にしましたが、うまくいかなかったですが、私は最終的にこれで使えるようになりました。<br>
個人個人で`rails_helper.rb`や`spec_helper.rb`の書き方違ったりするようなので、私の場合これでうまくいったという点を考慮して、試してもらえればと思います。

#参考記事
[【Rails】Rspecでマクロを定義して処理を共通化する方法](https://qiita.com/matsubishi5/items/6df9f14e5daa5e0dc1c8)
[deviseを使ったコントローラのテスト](https://qiita.com/nysalor/items/ef3d658ff76bee165379)