はじめに
RSpecにおいてshoulda-matchers
というgemがあります。
とても便利で、RSpecを簡潔に書く事ができます。
環境
rails (7.0.4)
rspec-rails (6.0.1)
shoulda-matchers (5.3.0)
shoulda-matchersとは
RSpecと互換性があり、RSpecのコードを簡潔に記述する事ができるgemです。
主にモデルのバリデーションで使用します。
参考:Shoulda Matchers
導入
Gemに追加
Gemfile
gem "shoulda-matchers"
インストール
ターミナル
bundle install
spec/rails_helper.rb
に以下を記述(もしくはsupportファイル)
spec/rails_helper.rb
RSpec.configure do |config|
#...省略
#...
end
#以下追記
Shoulda::Matchers.configure do |config|
config.integrate do |with|
with.test_framework :rspec
with.library :rails
end
end
使い方(使用頻度の高いものを抜粋)
よく使うバリデーションや設定を書いていきます。
詳しく知りたい方はこちらのREADMEをご覧ください。
presence
User.rb
class User < ApplicationRecord
validates :email, presence: true
end
spec/models/user_sepc.rb
require 'rails_helper'
RSpec.describe User, type: :model do
it { is_expected.to validate_presence_of :name }
end
uniqueness
User.rb
class User < ApplicationRecord
validates :name, uniqueness: true
end
spec/models/user_sepc.rb
require 'rails_helper'
RSpec.describe User, type: :model do
it { should validate_uniqueness_of(:email) }
end
※Deviseを使用していたり、DBに保存する前にdowncase
などで加工しているとエラーが発生します。
その場合は以下のようにします。 参考
spec/models/user_sepc.rb
require 'rails_helper'
RSpec.describe User, type: :model do
it { should validate_uniqueness_of(:email).ignoring_case_sensitivity }
end
length
User.rb
class User < ApplicationRecord
validates :name, length: { minimum: 3 }
validates :name, length: { maximum: 6 }
validates :password, length { in: 6..10 }
end
spec/models/user_sepc.rb
require 'rails_helper'
RSpec.describe User, type: :model do
it { is_expected.to validate_length_of(:name).is_at_least(3) }
it { is_expected.to validate_length_of(:name).is_at_most(6) }
it do
is_expected.to validate_length_of(:password).
is_at_least(6).
is_at_most(10)
end
end
has_secure_password
User.rb
class User < ApplicationRecord
has_secure_password
has_secure_password :reset_password
end
spec/models/user_sepc.rb
require 'rails_helper'
RSpec.describe User, type: :model do
it { is_expected.to have_secure_password }
it { is_expected.to have_secure_password(:reset_password) }
end
belongs_to
Person.rb
class Person < ApplicationRecord
belongs_to :organization
end
spec/models/person_sepc.rb
require 'rails_helper'
RSpec.describe Person, type: :model do
it { is_expected.to belong_to(:organization) }
end
has_many
User.rb
class User < ApplicationRecord
has_many :shirts, -> { order('color') }
end
spec/models/user_sepc.rb
require 'rails_helper'
RSpec.describe User, type: :model do
it { is_expected.to have_many(:shirts).order('color') }
end
dependent
User.rb
class User < ApplicationRecord
has_many :tweets, dependent: :destroy
end
spec/models/user_sepc.rb
require 'rails_helper'
RSpec.describe User, type: :model do
it { is_expected.to have_many(:tweets).dependent(:destroy) }
end
through
Person.rb
class Person < ApplicationRecord
has_many :acquaintances, through: :friends
end
spec/models/person_sepc.rb
require 'rails_helper'
RSpec.describe Person, type: :model do
it { is_expected.to have_many(:acquaintances).through(:friends) }
end
source
Person.rb
class Person < ApplicationRecord
has_many :job_offers, through: :friends, source: :opportunities
end
spec/models/person_sepc.rb
require 'rails_helper'
RSpec.describe Person, type: :model do
it do
should have_many(:job_offers).
through(:friends).
source(:opportunities)
end
end
has_one
Tweet.rb
class Tweet < ApplicationRecord
has_one :image
end
spec/models/tweet_sepc.rb
require 'rails_helper'
RSpec.describe Tweet, type: :model do
it { is_expected.to have_one_attached(:image) }
end
has_many
Tweet.rb
class Tweet < ApplicationRecord
has_one :images
end
spec/models/tweet_sepc.rb
require 'rails_helper'
RSpec.describe Tweet, type: :model do
it { is_expected.to have_many_attached(:images) }
end