最近、RSpecを使ってオリジナルアプリのテストを実装しているのですが、新規登録で詰まったところがあるので、メモしておきたいと思います(といっても非常に単純なことなのですが😅)。
詰まったこと
まず、ユーザーモデルのバリデーションは以下の通りです。
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
# ニックネームのバリデーション
validates :nickname, presence: true, length: { maximum: 30 }
# メールのバリデーション
EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i.freeze
validates :email, format: { with: EMAIL_REGEX }
# パスワードのバリデーション
PASSWORD_REGEX = /\A(?=.*?[a-z])(?=.*?\d)[a-z\d]+\z/i.freeze
validates_format_of :password, with: PASSWORD_REGEX, message: 'は英字と数字の両方を含めて6文字以上のものを設定してください', on: :create
今回詰まった結合テストは以下の通りです。
require 'rails_helper'
RSpec.describe "Users", type: :system do
let!(:user) { FactoryBot.create(:user) }
scenario "新規登録を行う" do
# トップページを開く
visit root_path
find('div[class="menu-wrapper"]').click
# メニューボタンをクリックすると、新規登録ボタンがある。
expect(page).to have_content('新規登録')
find('a[class="login"]').click
# 新規登録画面へ移動する。
visit new_user_registration_path
# ニックネームを入力
fill_in 'nickname', with: user.nickname
# メールアドレスを入力
fill_in 'メールアドレス', with: user.email
# パスワードを入力
fill_in 'パスワード', with: user.password
# 確認用パスワードを入力
fill_in 'パスワード(再入力)', with: user.password_confirmation
# 会員登録ボタンをクリックすると、ユーザーモデルのカウントが1上がる
expect{
find('input[name="commit"]').click
}.to change{ User.count }.by(1)
end
end
FactoryBotに設定したテストデータはこちらです。
FactoryBot.define do
factory :user, aliases: [:follow] do
nickname { Faker::Lorem.characters(number: 30) }
email { Faker::Internet.free_email }
password = 'a12345'
password { password }
password_confirmation { password }
end
end
この状態で「bundle exec rspec」を実行すると……
1) Users 新規登録を行う
Failure/Error:
expect{
find('input[name="commit"]').click
}.to change{ User.count }.by(1)
expected `User.count` to have changed by 1, but was changed by 0
[Screenshot]: /Users/○○/……/failures_r_spec_example_groups_users_新規登録を行う_○○.png
(中略)
ユーザーの新規登録を正常に行うことができませんでした。screenshotを確認したところ、どうやらemailに設定している
「他のユーザーが既に登録しているメールアドレスを登録することはできない(重複できない)」
というバリデーションに引っかかった模様。
そこで、rails_helpers.rbの記述を見直したり、FactoryBotのemailカラムに使っているFakerというGemについて調べたりしていたのですが、次の方法で解決しました。
require 'rails_helper'
RSpec.describe "Users", type: :system do
# createではなく、buildを使用
let!(:user) { FactoryBot.build(:user) }
scenario "新規登録を行う" do
(中略)
end
end
上記のように、createメソッドではなくbuildメソッドを使用することでテストが成功しました。
createメソッドを使うと、FactoryBotで生成したnickname、email、password、password_confirmationがデータベースに保存されます。つまり、既に登録されているemailを再び、
「fill_in 'メールアドレス', with: user.email」
で入力して登録しようとしていたわけですね。
そのため、「メールアドレスは重複して保存することはできません!」というバリデーションに引っかかったのでした。
というわけで、非常に単純なことでしたが😅
設定しているバリデーションを確認しながら、「createメソッドとbuildメソッドのどちらを使うべきか」を判断しなければならないことを学びました。最近はcreateメソッドばかりを使っていたので、視野を広く持たなければいけないなと感じました。
以上です。もし何か誤りなどありましたらご指摘いただけますと幸いです。
ここまで読んでいただきありがとうございました。