🐥

railsのバリデーションテストでつまずいた話

2023/08/28に公開

Railsのバリデーションテストの動作について

Railsのモデルのバリデーションテストは、一般的にshoulda-matchersというGemを使って書かれることが多いです。しかし、このGemのテストマッチャはどのように動作しているのでしょうか?そして、なぜ予期しないエラーが出ることがあるのでしょうか。この記事では、その背後にある動作をコード例を用いて解説します。

属性のみのバリデーションを実行するマッチャ

  • validate_presence_of
  • validate_absence_of

これらのマッチャは、特定の属性に焦点を当てたテストを行います。

# modelの例
class User < ApplicationRecord
  validates :name, presence: true
end

# testの例
it { should validate_presence_of(:name) }

このテストはnamenilに設定して、その属性のpresenceバリデーションが働くかどうかを確認します。

全体のバリデーションを実行するマッチャ

  • validate_numericality_of
  • validate_inclusion_of
  • validate_exclusion_of
  • validate_uniqueness_of

これらのマッチャは、特定の属性だけでなく、モデル全体のバリデーションを実行します。

# modelの例
class Product < ApplicationRecord
  validates :price, numericality: { greater_than: 0 }
  validates :category, presence: true
end

# testの例
it { should validate_numericality_of(:price).is_greater_than(0) }

このテストはprice0-1などに設定した後で、全体のバリデーションを実行します。そのため、もしcategoryが正しく設定されていなければ、予期しないエラーが発生することがあります。

予期しないエラーの原因

特定の属性だけを設定して、他の属性を設定しない場合、デフォルト値(通常はnil)が使用されます。全体のバリデーションを実行するマッチャを使用する場合、他の属性も適切に設定しておく必要があります。

# testの前準備例
before do
  subject.category = "Electronics"
end

まとめ

Railsのモデルバリデーションテストを書く際には、どのようなマッチャがどのように動作するのかを理解することが重要です。特に、全体のバリデーションを実行するマッチャを使用する際には、他の属性も適切に設定しておくことをおすすめします。

Discussion