初学者です。
テストコードがなぜか大好きです。
今回は結合テストコードについてまとめます。
Capybaraという標準で導入されているGemを利用しています。
前提条件
- FactoryBotを導入済みである
上記については以下の記事にまとめています。
【Ruby on Rails】FactoryBotとFakerについてまとめ
テストコードの種類
モデルやコントローラーなど機能ごとに問題がないか確認します。
例えばバリデーションがきちんと動作しているかなどです。
ユーザーがブラウザで操作する一連の流れを再現して問題がないか確かめます。
例えば、ユーザー登録で「名前とメールアドレスとパスワードを入力するとトップページに遷移して表示がユーザーの名前に変わっている」などの一連の動作を確認します。
ユーザーが開発者の意図する操作を行った時の挙動を確認するテストコードです。
例えば、ユーザー登録で問題なく全てのデータが入力された場合などです。
ユーザーが開発者の意図しない操作を行った時の挙動を確認するテストコードです。
例えば、ユーザー登録で正しい値が入っていないと登録できないかどうかなどです。
準備
今回はUserモデルの結合テストコードを例にしていきます。
まずは下記コマンドで結合テストコードを書くファイルを準備します。
rails g rspec:system users
spec/system配下にusers_spec.rbというファイルが生成されていればOKです。
テストコード
解説はあとにして先に記述例を載せます。
require 'rails_helper'
RSpec.describe 'ユーザー新規登録', type: :system do
before do
@user = FactoryBot.build(:user)
end
context 'ユーザー新規登録ができるとき' do
it '正しく情報を入力すればユーザー新規登録ができてトップページに移動する' do
# トップページに移動する
visit root_path
# トップページに新規登録ページへ遷移するボタンがあることを確認する
expect(page).to have_content('新規登録')
# 新規登録ページへ移動する
visit new_user_registration_path
# ユーザー情報を入力する
fill_in 'name', with: @user.nickname
fill_in 'Email', with: @user.email
fill_in 'Password', with: @user.password
fill_in 'Password confirmation', with: @user.password_confirmation
# 登録ボタンを押すとユーザーモデルのカウントが1増えることを確認する
expect{
find('input[name="button"]').click
}.to change { User.count }.by(1)
# トップページへ遷移することを確認する
expect(current_path).to eq(root_path)
# カーソルを合わせるとログアウトボタンが表示されることを確認する
expect(
find('.user_nav').find('span').hover
).to have_content('ログアウト')
# 新規登録ページへ遷移するボタンやログインページへ遷移するボタンが表示されていないことを確認する
expect(page).to have_no_content('新規登録')
expect(page).to have_no_content('ログイン')
end
end
context 'ユーザー新規登録ができないとき' do
it '誤った情報ではユーザー新規登録ができずに新規登録ページへ戻ってくる' do
# トップページに移動する
visit root_path
# トップページに新規登録ページへ遷移するボタンがあることを確認する
expect(page).to have_content('新規登録')
# 新規登録ページへ移動する
visit new_user_registration_path
# ユーザー情報を入力する
fill_in 'name', with: ''
fill_in 'Email', with: ''
fill_in 'Password', with: ''
fill_in 'Password confirmation', with: ''
# 登録ボタンを押してもユーザーモデルのカウントが増えないことを確認する
expect{
find('input[name="button"]').click
}.to change { User.count }.by(0)
# 新規登録ページへ戻されることを確認する
expect(current_path).to eq('/users')
end
end
end
RSpec.describe 'ログイン', type: :system do
before do
@user = FactoryBot.create(:user)
end
context 'ログインができるとき' do
it '保存されているユーザーの情報と合致すればログインができる' do
# トップページに移動する
visit root_path
# トップページにログインページへ遷移するボタンがあることを確認する
expect(page).to have_content('ログイン')
# ログインページへ遷移する
visit new_user_session_path
# 正しいユーザー情報を入力する
fill_in 'Email', with: @user.email
fill_in 'Password', with: @user.password
# ログインボタンを押す
find('input[name="button"]').click
# トップページへ遷移することを確認する
expect(current_path).to eq(root_path)
# カーソルを合わせるとログアウトボタンが表示されることを確認する
expect(
find('.nav_bar').find('span').hover
).to have_content('ログアウト')
# サインアップページへ遷移するボタンやログインページへ遷移するボタンが表示されていないことを確認する
expect(page).to have_no_content('新規登録')
expect(page).to have_no_content('ログイン')
end
end
context 'ログインができないとき' do
it '保存されているユーザーの情報と合致しないとログインができない' do
# トップページに移動する
visit root_path
# トップページにログインページへ遷移するボタンがあることを確認する
expect(page).to have_content('ログイン')
# ログインページへ遷移する
visit new_user_session_path
# ユーザー情報を入力する
fill_in 'Email', with: ''
fill_in 'Password', with: ''
# ログインボタンを押す
find('input[name="button"]').click
# ログインページへ戻されることを確認する
expect(current_path).to eq(new_user_session_path)
end
end
end
まずdescribeで新規登録の場合とログインの場合で項目分けします。
次にcontextでそれぞれ正常系と異常系で項目分けします。
そのあと、それぞれの流れを書いていきます。
FactoryBotについては新規登録はbuildですが、ログインはユーザー情報があらかじめあることが前提なのでcreateにしています。
では内容について細かく解説していきます。
visit
トップページに移動するをvisit root_pathとしています。
visitは遷移するという意味で利用します。
page
visitで訪れた先のページの情報が格納されています。例えばカーソルを合わせてはじめて見ることができる文字列はpageの中に含まれません。
have_content
トップページに新規登録ページへ遷移するボタンがあることを確認するをexpect(page).to have_content('新規登録')としています。
visitで訪れたpageの中に該当の文字列があるかどうかを判断する時に利用します。
fill_in
ユーザー情報を入力するはfill_inを利用しています。
fill_in フォームの名前, with: 入力する文字列と記述することでフォームへの入力を行うことができます。
find().click
find(クリックしたい要素).clickと記述することでクリックの動作ができます。
登録ボタンを押すとユーザーモデルのカウントが1増えることを確認するを登録ボタンを押すの動作をfind('input[name="button"]').clickで表しています。
この場合はinput要素のname="button"を指定していることになります。
change
expect{ 動作 }.to change { モデル名.count }.by(1)で登録ボタンを押すとユーザーモデルのカウントが1増えることを確認するの
カウントが1増えるを表しています。
current_path
トップページへ遷移することを確認するをexpect(current_path).to eq(root_path)としています。
current_pathは今いるページという意味です。
hover
find(要素).hoverで特定の要素にカーソルをあわせたときの動作を表すことができます。
カーソルを合わせるとログアウトボタンが表示されることを確認するをexpect(find('.nav_bar').find('span').hover).to have_content('ログアウト')としています。
今回の場合は.nav_barの中のspan要素という感じで二重に探しています。
have_no_content
サインアップページへ遷移するボタンやログインページへ遷移するボタンが表示されていないことを確認するをexpect(page).to have_no_content('新規登録')とexpect(page).to have_no_content('ログイン')としています。
存在しないことを確認するという意味です。
以上です。