LoginSignup
2
2

More than 5 years have passed since last update.

shared_exampleを使ってrequire_login関係のrspecの重複を減らす

Last updated at Posted at 2015-03-30

テストの冗長を減らせる良い書き方だと思ったので、自分への備忘録も兼ねて、情報を共有します。

実現方法

shared_exampleを使って下記の処理をまとめました。

  • require_loginに引っかかった時の確認項目
  • require_loginに引っかからないためのcurrent_userの定義

冗長な部分をまとめた例

spec/controllers/books_controller_spec.rb
RSpec.describe BooksController, type: :controller do
  describe 'GET #new' do

    it_behaves_like 'before login', :get :new

    it_behaves_like 'after login as a user' do
      it 'render_template :new' do
        get :new
        expect(response).to render_template(:new)
      end
    end
  end

  describe 'POST #create' do

    it_behaves_like 'before login', :post, :create, { book: { name: 'メタプログラミングRuby' } }

    it_behaves_like 'after login as a user' do

      it 'if succeeded posting, render template :show' do
        post :create, { book: { name: 'メタプログラミングRuby' } }
        expect(response).to render_template(:show)
      end

      it 'if failed posting, render template :new' do
        post :create, { book: { name: '' } }
        expect(response).to render_template(:new)
      end
    end
  end
end
spec/support/shared_examples.rb
# require_loginに引っかかった時の確認項目
shared_examples 'before login' do |method, template, params|
  before do
    send(method, template, params)
  end
  it 'redirect to login' do
    expect(response).to redirect_to(login_path)
  end
end

# require_loginに引っかからないためのcurrent_userの定義
shared_examples 'after login as a user' do
  before do
    user = User.first
    if user.blank?
      user = User.create(email: 'test@example.com', password: 'testpassword', password_confirmation: 'testpassword')
      user.activate!
    end
    allow(controller)
      .to receive(:current_user)
      .and_return(user)
  end
end

冗長な例

重複をまとめずに書いていたときは、自分の場合こうなっていました。

spec/controllers/books_controller_spec.rb
RSpec.describe BooksController, type: :controller do

  describe 'GET #new' do
    # require_loginに引っかかった場合の処理を毎回書きたくない
    it 'before login' do
      get :new
      expect(response).to redirect_to(login_path)
    end

    describe 'after login as a user' do
      # current_userの定義を毎回に書きたくない
      before do
        user = User.first
        if user.blank?
          user = User.create(email: 'test@example.com', password: 'password', password_confirmation: 'password')
          user.activate!
        end
        allow(controller)
          .to receive(:current_user)
          .and_return(user)
      end

      it 'render_template :new' do
        get :new
        expect(response).to render_template(:new)
      end
    end
  end

  describe 'POST #create' do

    # newの場合とほとんど同じ
    it 'before login' do
      post :create, { book: { name: 'メタプログラミングRuby' } }
      expect(response).to redirect_to(login_path)
    end

    it 'after login as a user' do

      # newの場合とほとんど同じ
      before do
        user = User.first
        if user.blank?
          user = User.create(
            email: 'test@example.com',
            password: 'password',
            password_confirmation: 'password'
          )
          user.activate!
        end
        allow(controller)
          .to receive(:current_user)
          .and_return(user)
      end

      it 'if succeeded posting, render template :show' do
        post :create, { book: { name: 'メタプログラミングRuby' } }
        expect(response).to render_template(:show)
      end

      it 'if failed posting, render template :new' do
        post :create, { book: { name: '' } }
        expect(response).to render_template(:new)
      end
    end
  end
end

以上です。
誰かのお役に立てれば幸いです。

参考:
http://d.hatena.ne.jp/yohfee/20110222/1298384637
http://qiita.com/asukiaaa/items/2dd7ed44f6903bc15055

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2