2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【RSpec】ユーザーの新規登録について結合テストを行う時に意識すること

Posted at

 最近、RSpecを使ってオリジナルアプリのテストを実装しているのですが、新規登録で詰まったところがあるので、メモしておきたいと思います(といっても非常に単純なことなのですが😅)。

詰まったこと

 まず、ユーザーモデルのバリデーションは以下の通りです。

app/models/user.rb
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

 今回詰まった結合テストは以下の通りです。

spec/system/users_spec.rb
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に設定したテストデータはこちらです。

spec/factories/users.rb
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について調べたりしていたのですが、次の方法で解決しました。

spec/system/users_spec.rb
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メソッドばかりを使っていたので、視野を広く持たなければいけないなと感じました。

 以上です。もし何か誤りなどありましたらご指摘いただけますと幸いです。
 ここまで読んでいただきありがとうございました。

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?