見出し画像

Rspecのエラーメッセージのキー情報だけを参照して行うmodelテストの書き方について

どうもひっきーです。しばらくぶりの投稿になってしました。

現在ポートフォリオのRspecのコードを作成しており、その中でより汎用性のあるテストコードの書き方を一部学習したのでその内容をまとめます。

今回はチェリー本の著者である伊藤さんのこちらの記事を参考にRspecのコードを書き換えてみました。

例えば、userモデルに関するテストで、emailのカラムに関する一意性のバリデーションテストを行いたい場合は、以下のように書くことができます。

require 'rails_helper'

describe User do
 ~~
 it "重複したメールアドレスではアカウントが作れないこと" do
   FactoryBot.create(:user, email: "test@mail.com")
   user = FactoryBot.build(:user, email: "test@mail.com")
   user.valid?
   expect(user.errors[:email]).to include("has already been taken")
  end
~~
end

このように、ユーザーが無効であった場合に、includeメゾットを使って、emailカラムのエラーメッセージに指定したメッセージが含まれているかを確認することができます。しかし、含まれているエラーの文面を直接書くため、テストが各国の言語に依存してしまうというデメリットがあります。この問題を解決するために、上の記事にて説明されている、エラーメッセージのキー情報だけを参照して行うmodelテストの書き方について学習してみました。

キー情報のみを参照した場合のコードの基本形は以下のようになります。

今回はpredicateマッチャを使った場合の書き方を参考にしました。

expect(user.errors).to be_added('テストするカラム', '第2引数キー', '第3引数キー')

ここから、コンソールを使ったエラーの種類に合わせて引数に与えるキーの確認方法を説明します。

今回はあらかじめ、test@mail.comというメールアドレスをもつデータをDBに用意しておきます。プロジェクトのコンソール上で次のようにtest@mail.comのアカウントを作ろうとすると、もちろんアカウントは作成されません。

#rails c
pry(main)> user = User.create(name: 'john', email: 'test@mail.com')
  (0.1ms)  begin transaction
 User Exists (5.0ms)  SELECT  1 AS one FROM "users" WHERE LOWER("users"."email") = LOWER(?) LIMIT ?  [["email", "test@mail.com"], ["LIMIT", 1]]
  (0.1ms)  rollback transaction

続けてエラーメッセージの詳細を調べるために、エラーメッセージのキーを指定して出力します。

[15] pry(main)> user.errors.details[:email]
=> [{:error=>:taken, :value=>"test@mail.com"}]

この結果から、今回のユーザーのemailの一意性に関するrspecのテストコードを書くためには、第2引数としてtakenキー、第3引数にvalueキーと入力するアドレスを値として与える必要があることがわかります。

以上を踏まえて先ほどのrspecコード内で第3引数を与えた場合のコードは次のようになります。

# user_spec.rb
it "重複したメールアドレスではアカウントが作れないこと" do
   FactoryBot.create(:user, email: "test@mail.com")
   user = FactoryBot.build(:user, email: "test@mail.com")
   user.valid?
   expect(user.errors).to be_added(:email, :taken, value: "test@mail.com")
 end

テストをパスすることができました。

$ bundle exec rspec
Finished in 0.10993 seconds (files took 1.53 seconds to load)
10 examples, 0 failures, 3 pending

他にも、例えばパスワードの再入力が一致していない場合は

第2引数にconfirmationキー、第3引数にattributeキーとPasswordの値が必要であることが確認できます。

# rails c
 pry(main)> user.errors.details[:password_confirmation]
=> [{:error=>:confirmation, :attribute=>"Password"}]

これらを使って引き続き自分のテストコードをブラッシュアップしていきます。


この記事が気に入ったらサポートをしてみませんか?