ログインmoduleでDRYに

はじめに

10月からRunteqの課題取組中
駆け出しエンジニアです.
日々の学びをアウトプットします.
beforeに触れてますが、挙動までは触れません.

概要

  • ログイン処理で重複しがち
  • サポートモジュール作成
  • コードがスッキリ

    ログイン処理で重複しがち

  • コード例
require 'rails_helper'
RSpec.feature "Users", type: :feature do
  describe 'ログイン後' do
    let(:user) {build(:user)}
    describe 'ユーザー編集'  do
      context 'フォームの入力値が正常'  do
        it 'ユーザーの編集が成功する' do
          #ログイン処理 1回目
          visit root_path
          click_link 'Login'
          fill_in 'Email', with: user.email
          fill_in 'Password', with: 'password'
          click_button 'Login'
          #編集の処理・・・
        end
      end
      context 'メールアドレスが未入力'  do
        it 'ユーザーの編集が成功する' do
          #ログイン処理 2回目
          visit root_path
          click_link 'Login'
          fill_in 'Email', with: user.email
          fill_in 'Password', with: 'password'
          click_button 'Login'
          #編集の処理・・・
         end
      end
      context '登録済みのメールアドレスを使用' do
        it 'ユーザーの編集が失敗する' do
          #ログイン処理 3回目
          visit root_path
          click_link 'Login'
          fill_in 'Email', with: user.email
          fill_in 'Password', with: 'password'
          click_button 'Login'
          #編集の処理・・・
        end
      end
    end
  end
end
      

編集のテストを実行するたびに、ログイン処理でコードが重複してしまいます.
これでは記述するのも大変ですし、コードが重複します.

  • beforeを使ってDRYに
require 'rails_helper'
RSpec.feature "Users", type: :feature do
  describe 'ログイン後' do
    let(:user) {build(:user)}
    before do
      #ログイン処理
      click_link 'Login'
      fill_in 'Email', with: user.email
      fill_in 'Password', with: 'password'
      click_button 'Login'
    end
    describe 'ユーザー編集'  do
      context 'フォームの入力値が正常'  do
        it 'ユーザーの編集が成功する' do
          #編集の処理・・・
        end
      end
      context 'メールアドレスが未入力'  do
        it 'ユーザーの編集が成功する' do
           #編集の処理・・・
         end
      end
      context '登録済みのメールアドレスを使用' do
        it 'ユーザーの編集が失敗する' do
           #編集の処理・・・
        end
      end
    end
  end
end
      

これでもスッキリしたのですが、別のテストでもログイン処理は使いますよね...
例えば下のような実装がされているアプリがあったとします.

f:id:takishita0:20210221151553p:plain Project、Noteがログインしたユーザでなければ作成できないとすると、テストを書くたびにログイン処理のコードが重複してしまいます.
下のような共通で使えるメソッドあれば、便利ですよね!

def sign_in_as(user)
  visit root_path
  click_link 'Login'
  fill_in 'Email', with: user.email
  fill_in 'Password', with: 'password'
  click_button 'Login'
end

  #1行で済む
  sign_in_as user

サポートモジュール作成

  • 別ファイルにログイン処理を切り出す
    共通で使えるモジュールを作成します.
    spec/supportディレクトリにLogin_support.rbという名前のファイルを作成します.
    ファイルの中にログイン処理のコードを記述します.
#spec/support/Login_support.rb
module LoginSupport
  def sign_in_as(user)
    visit root_path
    click_link 'Login'
    fill_in 'Email', with: user.email
    fill_in 'Password', with: 'password'
    click_button 'Login'
  end
end

# Rspec設定に読み込ませる
RSpec.configure do |config|
  config.include LoginSupport
end

モジュールの定義のあとにあるコードはモジュールを読み込ませるコードです.
読み込ませる別の方法としてconfig.include LoginSupportをspec/rails_helper.rb内に記述する方法もあります.
最後にspec/rails_helper.rb内の以下のコードがコメントアウトされているので、有効化してください.

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

これで準備が整いました.

コードがスッキリ

スッキリしました.
このモジュールは他のテストでも使い回せるので、コードの重複が少なくなりスッキリしますね.

require 'rails_helper'
RSpec.feature "Users", type: :feature do
  describe 'ログイン後' do
    let(:user) {build(:user)}
    before do
      #ログイン処理
      sign_in_as user
    end
    describe 'ユーザー編集'  do
      context 'フォームの入力値が正常'  do
        it 'ユーザーの編集が成功する' do
          #編集の処理・・・
        end
      end
      context 'メールアドレスが未入力'  do
        it 'ユーザーの編集が成功する' do
           #編集の処理・・・
         end
      end
      context '登録済みのメールアドレスを使用' do
        it 'ユーザーの編集が失敗する' do
           #編集の処理・・・
        end
      end
    end
  end
end