テストの冗長を減らせる良い書き方だと思ったので、自分への備忘録も兼ねて、情報を共有します。
実現方法
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