91
87

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 5 years have passed since last update.

【Rails】まだValidatorのテストで消耗してるの?

Last updated at Posted at 2015-03-30

Custom Validator

RailsにおけるCustom ValidatorについてはRuby on Rails Guidesや「てめえらのRailsはオブジェクト指向じゃねえ!まずはCallbackクラス、Validatorクラスを活用しろ!」などの記事に触れられているとおりである.
Modelはごちゃごちゃさせたくないし,Validatorとして切りだしちゃえば使い回しも効くよね!という話(ざっくり).

Validatorのテスト

Custom ValidatorのテストについてはRailsでCustom validatorをテストするにて言及されている.
特定のModelに依存したテストを書くのはおかしな話だからダミーのクラスを用意しよう!みたいな感じ.

let(:model_class) do
  Struct.new(:url) do
    include ActiveModel::Validations

    def self.name
      'DummyModel'
    end

    validates :url, full_http_url: true
  end
end

- RailsでCustom validatorをテストする - Qiita

ただ,これを各Validator Spec毎に毎回書くのは面倒だなーと思う.サボりたい.

RSpec::ValidatorSpecHelper

ということで,Validatorのテストで手抜きするためのgemを作った(izumin5210/rspec-validator_spec_helper).
勝手にダミークラスを生成してvalidatesvalidates_withも設定してくれるというものになっている.

EachValidator継承クラスの場合は1つのカラムにしか依存しないので,letを利用してvalueに値を突っ込むことでvalidateしてくれる.
あとはis_expectedやワンライナーshould等でbe_valid/be_invalidを見てあげればよい(subjectにダミークラスをnewしたものが入ってる).

describe EmailValidator, type: :validator do
  describe '#validate_each' do
    context 'with invalid format address' do
      let(:value) { 'kokoro.pyonpyon' }
      it { is_expected.to_not be_valid }
    end

    context 'with valid foramt address' do
      let(:value) { 'kokoro.pyonpyon@example.com' }
      it { is_expected.to be_valid }
    end
  end
end

EachValidatorじゃない(Validatorを直接継承している)場合は,validationに関係するカラム名をattribute_namesとして渡してあげる.

describe NotOverlappedValidator, type: :validator do
  let(:attribute_names) { [:begin_at, :end_at] }
  let(:begin_at) { Time.parse("2014-12-24T12:00:00+09:00") }

  describe '#validate' do
    context 'when end_at is overlapped' do
      let(:end_at) { Time.parse("2014-12-24T09:00:00+09:00") }
      it { is_expected.to_not be_valid }
    end

    context 'when end_at is not overlapped' do
      let(:end_at) { Time.parse("2014-12-24T19:00:00+09:00") }
      it { is_expected.to be_valid }
    end
  end
end

値を宣言するだけでValidationのテストができるので,とても楽になる.

References

91
87
1

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
91
87

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?