初学者の備忘録です!間違い等あればご指摘お願いいたします!
非常に分かりやすい参考記事様 ▶︎https://qiita.com/jnchito/items/2e79a1abe7cd8214caa5
- Ruby2.6.5
- Rails6.0.0
前提
こちらの記事では、Rspecを導入した後の手順を記述しております。
未実装の方はこちらを参考にどうぞ→Rspecの導入方法
結合テストコードの準備
結合テストコードは、単体テストコードのように一つ一つの項目のテストだけでなく、ユーザーが辿るであろう一連の流れを確認するためのものです!
単体を一つの流れにくっ付ける、その名の通り**「結合テスト」**ですね!
単体と違う部分は他にもあり、実行コマンドの変化や、**「Capybara」**というGemを使います!
順に見ていきましょう!
System Spec
System Specは、結合テストコードを記述するための仕組みです。
Capybara
Capybara(カピバラ)はSystem Specを記述するために必要なGemのことです。
Gemfileを確認すると、すでに搭載されていることが分かります!
Gemfile
group :test do
# Adds support for Capybara system testing and selenium driver
gem 'capybara', '>= 2.15'
(略)
end
System Spec(結合テストコードの仕組み)を使うために、CapybaraというGemを使ってく、というイメージです!
では、早速結合テストコードを書いていきましょう!
テストコードを記述するファイルの用意
単体テストと同様に、ターミナル上でファイルを生成していきます!
(今回もUserに関するテストコードを記述しますので、記述したいテストにより名前を変えてください!)
ターミナル
rails g rspec:system users
今回の場合、spec/system/users_spec.rbというファイルを作りました!
systemディレクトリ内に入ってるのが結合テストコードってことですね!
exampleの整理(何をどのような流れでテストするのか?)
単体テストコードでは詳細の記述をしませんでしたが、テストコードを書く上で一番大事と言っても過言ではないです。
特に結合テストコードでは一連の流れを考えるわけですからね!
細かく言語化することが重要です。私は実際にユーザーになって動くたびに挙動の記述を繰り返して書いてます!
テストコードに落とし込み、記述
exampleを書き出したらさっき作ったファイルに書いていきます!(以下は例です)
exampleについては#でコメントアウトします。
spec/system/users_spec.rb
require 'rails_helper'
RSpec.describe 'ユーザー新規登録', type: :system do
before do
@user = FactoryBot.build(:user)
end
context 'ユーザー新規登録ができるとき' do
it '正しい情報を入力すればユーザー新規登録ができてトップページに移動する' do
# トップページに移動する
# トップページにサインアップページへ遷移するボタンがあることを確認する
# 新規登録ページへ移動する
# ユーザー情報を入力する
# サインアップボタンを押すとユーザーモデルのカウントが1上がることを確認する
# トップページへ遷移する
# カーソルを合わせるとログアウトボタンが表示されることを確認する
# サインアップページへ遷移するボタンや、ログインページへ遷移するボタンが表示されていないことを確認する
end
end
ここにコードの肉付けをしていきます!!
そのために必要なコードの記述方をみていきましょう。
新規登録がうまくいくときのテストコード(一例)
トップページに移動する
▶︎visit
visit 〇〇_pathのように記述すると、〇〇のページへ移動する挙動を表現します。
今回はトップということでroot_pathに指定してます。
rails routesで確認し記述しましょう!
# トップページに移動する
visit root_path
次にいきましょう!
トップページにサインアップページへ遷移するボタンがあることを確認する
▶︎page
visitで訪れたページの見える部分(画面上で見えているもの)の情報が保持されています。
「カーソルを合わせないと確認できない」場合は別メソッドhoverが必要です。(下記に記述しています)
# トップページにサインアップページへ遷移するボタンがあることを確認する
expect(page).to have_content('新規登録')
新規登録ページへ移動する
これはトップページに遷移すると同様なので省略します。
ユーザー情報を入力する
▶︎fill_in
fill_in 'フォームの名前', with: '入力する文字列'と記述することで、フォームへの入力を行うことができます。
勝手に書いてくれる優れものです!
フォームの名前は検証ツールやhtmlから確認できます。
※label要素のforに指定されているIDと、inputのidの値が同一になっていることを確認しましょう。
入力する文字列に関しては、Fakerなどを活用してみましょう!
visit new_user_registration_path
# ユーザー情報を入力する
fill_in 'Nickname', with: @user.nickname
fill_in 'Email', with: @user.email
fill_in 'Password', with: @user.password
fill_in 'Password confirmation', with: @user.password_confirmation
さぁどんどん行きましょう!
サインアップボタンを押すとユーザーモデルのカウントが1上がることを確認する
▶︎find().click
find('クリックしたい要素').clickと記述することで、実際にクリックができます。
ここでも検証ツールを使ってみましょう!
具体的には、input要素のname属性を指定します。
今回は、
****と記述してありました。
この場合、find('input[name="commit"]').clickという記述をすればokです。
サインアップのボタンを押すことは学びましたが、このままでは求めている挙動を満たしてません。
ユーザーモデルのカウントが1上がることの確認をどうするか?
ハイ!マッチャを使ってダブル使いします!
▶︎change
expect{ 行う動作 }.to change { モデル名.count }.by(1)と記述することで、モデルのレコードの数がいくつ変動するのかを確認をします。
(1)を(0)にすれば、動作しなかった場合のテストコードにも使えますね!
行う動作に先ほど覚えたfind('クリックしたい要素').clickを入れればok!
# サインアップボタンを押すとユーザーモデルのカウントが1上がることを確認する
expect{
find('input[name="commit"]').click
}.to change { User.count }.by(1)
トップページへ遷移する
ここでvisitを使いたくなりますがちょっと待ってください!
確かに移動するという点では同じです。しかし違う点があります!
今回は、新規登録をする→トップページにリダイレクトするという挙動を実現したいんですよね。
なので、今いるページがどこなのかを確認したいです。
そのときに使いたいのが**current_path(現在いるページのパスを自動指定)**です!
# トップページへ遷移したことを確認する
expect(current_path).to eq(root_path)
カーソルを合わせるとログアウトボタンが表示されることを確認する
▶︎hover
隠している特定の要素を確認することができます。クラスなどを指定する場合はその親要素の記述も必要になります!
expect(
find('.user_nav').hover
).to have_content('ログアウト')
サインアップページへ遷移するボタンや、ログインページへ遷移するボタンが表示されていないことを確認する
▶︎have_no_content
have_contentの逆です。文字列が存在しないことの確認ができます。
テストコードを実行する
ここまで記述お疲れ様でした!
最後に以下のコマンドで確認してください。
ターミナル
% bundle exec rspec spec/system/users_spec.rb
パソコン上でババーっと自動的に挙動確認をしてくれるはずです!
問題なく最後まで実行され、ターミナルにもエラー文が出なければ完成です!