はじめに
ポートフォリオに実際に実装したrequest specの部分です。
テストコードについては勉強したけどテストコードを実際に書く時にどんなことをテストすればいいか分からないと思ったのでそういった人の参考になれば嬉しいです。
テストしたのはCRUD機能部分です。
index
Controller
with_attached_eyecatch
はactive storageでN+1が起きないするためのメソッドです。
app/controllers/event_controller.rb
def index
@events = Event.with_attached_eyecatch.latest
end
request spec
subject
を使うことでリクエストを共通化しています。
spec/requests/events_spec.rb
describe 'GET #index' do
subject { get(events_path) }
context 'イベントが存在する場合' do
let!(:event) { create(:event, user_id: user.id) }
it 'リクエストが成功する' do
subject
expect(response).to have_http_status(200)
end
it 'name が表示されている' do
subject
expect(response.body).to include event.name
end
end
end
show
Controller
app/controllers/event_controller.rb
def show
@event = Event.find(params[:id])
end
request spec
spec/requests/events_spec.rb
describe 'GET #show' do
subject { get(event_path(event.id)) }
context 'イベントが存在する場合' do
let(:event) { create(:event, user_id: user.id) }
it 'リクエストが成功する' do
subject
expect(response).to have_http_status(200)
end
it 'name が表示されている' do
subject
expect(response.body).to include event.name
end
end
end
new
Controller
app/controllers/event_controller.rb
def new
@event = current_user.events.build
end
request spec
spec/requests/events_spec.rb
describe 'GET #new' do
subject { get(new_event_path) }
it 'リクエストが成功する' do
subject
expect(response).to have_http_status(200)
end
end
post
Controller
app/controllers/event_controller.rb
def create
@event = current_user.events.build(event_params)
if @event.save
redirect_to event_path(@event), notice: '作成しました'
else
flash.now[:error] = '作成に失敗しました'
render :new
end
end
request spec
パラメーターが必要なのでパラメーターが正常のテストと異常のテストの両方をテストします。
異常系のテストはバリデーションエラーが出ることをテストしています。
spec/requests/events_spec.rb
describe 'POST #create' do
subject { post(events_path, params: params) }
context 'パラメータが正常な場合' do
let(:params) { { event: attributes_for(:event) } }
it '投稿が保存される' do
expect { subject }.to change { Event.count }.by(1)
end
it 'リクエストが成功する' do
subject
expect(response).to have_http_status(302)
end
it 'イベント一覧ページにリダイレクトされる' do
subject
expect(response).to redirect_to('http://www.example.com/events?locale=ja')
end
end
context 'パラメータが異常な場合' do
let(:params) { { event: attributes_for(:event, :invalid) } }
it 'リクエストが成功する' do
subject
expect(response).to have_http_status(200)
end
it '投稿が保存されない' do
expect { subject }.not_to change(Event, :count)
end
it 'イベント投稿ページがレンダリングされる' do
subject
expect(response.body).to include I18n.t('events.form.event-post')
end
end
end
edit
Controller
app/controllers/event_controller.rb
def edit
@event = current_user.events.find(params[:id])
end
request spec
spec/requests/events_spec.rb
describe 'GET #edit' do
subject { get(edit_event_path(event_id)) }
context 'イベントが存在する場合' do
let(:event) { create(:event, user_id: user.id) }
let(:event_id) { event.id }
it 'リクエストが成功する' do
subject
expect(response).to have_http_status(200)
end
it 'name が表示されている' do
subject
expect(response.body).to include event.name
end
end
end
update
Controller
app/controllers/event_controller.rb
def update
@event = current_user.events.find(params[:id])
if @event.update(event_params)
redirect_to event_path(@event), notice: '更新しました'
else
flash.now[:error] = '更新に失敗しました'
render :edit
end
end
request spec
パラメーターが必要なので異常系のテストも必要。
createとの違いはデータの更新ができていることreload
メソッドを使うことで更新した値のテストが可能。
spec/requests/events_spec.rb
describe 'PATCH #update' do
subject { patch(event_path(event.id), params: params) }
let(:event) { create(:event, user_id: user.id) }
context 'パラメーターが正常な場合' do
let(:params) { { event: attributes_for(:event) } }
it 'リクエストが成功する' do
subject
expect(response).to have_http_status(302)
end
it 'name が更新される' do
origin_name = event.name
new_name = params[:event][:name]
expect { subject }.to change { event.reload.name }.from(origin_name).to(new_name)
end
end
context 'パラメータが異常なとき' do
let(:params) { { event: attributes_for(:event, :invalid) } }
it 'リクエストが成功する' do
subject
expect(response).to have_http_status(200)
end
it 'name が更新されない' do
expect { subject }.not_to change(event.reload, :name)
end
it 'イベント編集ページがレンダリングされる' do
subject
expect(response.body).to include I18n.t('events.form.event-edit')
end
end
end
destroy
Controller
app/controllers/event_controller.rb
def destroy
event = current_user.events.find(params[:id])
event.destroy!
redirect_to events_path, notice: '削除しました'
end
request spec
let!
とすることで各テストの最初に実行される。
spec/requests/events_spec.rb
describe 'DELETE #destroy' do
subject { delete(event_path(event.id)) }
let!(:event) { create(:event, user_id: user.id) }
context 'パラメータが正常な場合' do
it 'リクエストが成功する' do
subject
expect(response).to have_http_status(302)
end
it 'イベントが削除される' do
expect { subject }.to change(Event, :count).by(-1)
end
it 'イベント一覧にリダイレクトすること' do
subject
expect(response).to redirect_to('http://www.example.com/events?locale=ja')
end
end
end
以上です。
最後はsystem spec!