今回はRSpecの中トロ部分、system specでコントローラーのテストを実行していきます。
コントローラーのテストでは、実際に操作するような感覚でテストコードを書いていきます。
開発環境
ruby 2.6.3
Rails 5.2.6
前提
- FactoryBot使用
- Faker使用
- capybara使用
- devise使用
RSpecの準備、FactoryBotでのテストデータの定義等は、下記記事にまとめてますので、まだの方は先にこちらをどうぞ。
[Rails]RSpecでテストを行う準備(FactoryBot使用)
ファイルの作成
まずは、spec配下にsystemフォルダを作って、その中に各コントローラーのファイルを作っていきます。
今回は、
posts_spec.rb
を例にコードを記述していきます。
作成した各モデルのファイルで、rails_helperの設定を読み込んでいきます。
rails_helperはRSpecの設定が記述してあるファイルです。
コードを1行書くだけで、読み込めるので先に記述しておきます。
最初にまとめて書いておくことで、書き忘れを防げます!
require 'rails_helper'
deviseのヘルパーを使えるようにする
controllerのテストを実行していく中で、sign_inなどのdeviseのヘルパーを使う機会が出てきます。
なぜRSpecのコードを書いていくときに、deviseのヘルパーが必要かというと、アクセス権限でログインしてないユーザーを許可していない場合があるから
です。
ユーザーの編集ページはログインしてないときは、アクセスできないなど
spec/rails_helper.rb
にdeviseのヘルパーを使えるようにコードを追加します。
:
# deviseのヘルパーメソッドをsystemで使用できるように設定
config.include Devise::Test::IntegrationHelpers, type: :system
end
これでdeviseのヘルパーをsystemで使用できるようになりました。
capybaraの設定
systemでCapybaraを使ってテストできるように、spec_helper
に設定を追加します。
:
RSpec.configure do |config|
# 以下3行を追加
config.before(:each, type: :system) do
driven_by :rack_test
end
:
これでsystemでcapybaraが使えるようになりました。
テストコードを書いていく
posts_specでは投稿のテストと削除のテストを行います。
テスト項目の洗い出し
まずはテスト項目の洗い出しを行っていきます。
投稿のテストでは、成功したときと失敗したときのテストを書いていきます。
require 'rails_helper'
describe '投稿に関するテスト' do
describe "投稿のテスト" do
context "投稿が成功したとき" do
it "投稿成功後の遷移先が正しいか" do
# この中にテストの処理を書いていく
end
it "投稿成功後の表示の確認" do
# この中にテストの処理を書いていく
end
end
context "投稿が失敗したとき" do
it "投稿失敗後の遷移先が正しいか" do
# この中にテストの処理を書いていく
end
it "投稿失敗後の表示の確認" do
# この中にテストの処理を書いていく
end
end
end
describe "削除のテスト" do
it "削除リンクが表示されているか" do
# この中にテストの処理を書いていく
end
it "削除されるか" do
# この中にテストの処理を書いていく
end
end
end
RSpecの記述の基本形がわからない方はこちらの記事参照
最低限覚えておきたいRSpecの基本構成
テストデータをつくる
FactoryBotで作っておいたデータをつ使います。
わからない方は、こちらの記事で確認してください。
[Rails]RSpecでテストを行う準備(FactoryBot使用)
:
describe '投稿に関するテスト' do
# FactoryBotのテストデータを使う
let!(:user) { create(:user) }
let!(:post) { create(:post, user_id: user.id) }
describe "投稿のテスト" do
:
beforeを記述
投稿のテストも削除のテストもサインインしてから使う機能なので、サインインしてからテストを実行したいので、beforeでサインインしたあとに各ページに移動しておきます。
:
describe "投稿のテスト" do
# userでログインしてから新規投稿画面へ遷移
before do
sign_in user
visit new_post_path
end
:
describe "削除のテスト" do
# userでログインしてから投稿一覧へ遷移
before do
sign_in user
visit posts_path
end
:
テストの中身を記述
これで、準備ができたので、it
の中でテストを実行していきます。
コード内に解説を入れています。
require 'rails_helper'
describe '投稿に関するテスト' do
# FactoryBotのテストデータを使う
let!(:user) { create(:user) }
let!(:post) { create(:post, user_id: user.id) }
describe "投稿のテスト" do
before do
sign_in user
visit new_post_path
end
context "投稿が成功したとき" do
it "投稿成功後の遷移先が正しいか" do
# contentのフォームにFakerでランダムな5文字の文字列を入れる
fill_in 'post[content]', with: Faker::Lorem.characters(number: 5)
# 投稿ボタンをクリック
click_button "投稿"
# 投稿成功後の遷移先が期待したパスになっているか
expect(page).to have_current_path posts_path
end
it "投稿成功後の表示の確認" do
# contentのフォームにFakerでランダムな5文字の文字列を入れる
fill_in 'post[content]', with: Faker::Lorem.characters(number: 5)
# 投稿ボタンをクリック
click_button "投稿"
# 投稿が成功して"投稿が成功しました"の文字があるか
expect(page).to have_content "投稿に成功しました"
end
end
context "投稿が失敗したとき" do
it "投稿失敗後の遷移先が正しいか" do
# contentのフォームを空にする
fill_in 'post[content]', with: nil
# 投稿ボタンをクリック
click_button "投稿"
# エラーが起きて選先が期待したパスになっているか
expect(page).to have_current_path posts_path
end
it "投稿失敗後の表示の確認" do
# contentのフォームを空にする
fill_in 'post[content]', with: nil
# 投稿ボタンをクリック
click_button "投稿"
# エラーが出てエラーメッセージが表示されているか
expect(page).to have_content "入力してください"
end
end
end
describe "削除のテスト" do
before do
sign_in user
visit posts_path
end
it "削除リンクが表示されているか" do
# 削除のパスへのリンクがあるか
expect(page).to have_link "", href: post_path(post)
end
it "削除されるか" do
# 削除された時データベースから削除されているか
expect { post.destroy }.to change(Post, :count).by(-1)
end
end
end
マッチャーについてわからない方はこちらの記事参照
[Rails]RSpecでよく使うマッチャー10選
まとめ
system specでコントローラーのテストを実施する手順は4つです。
- system specファイルの作成
- deviseのヘルパーを使えるようにする
- capybaraの設定
- テストコードを書いていく
今回はかんたんな投稿と削除機能のみでしたが、今後も色んなテストコードを投稿していきたいと思います。