2011-12-19 23 views
4

最近、ShouldaとRspecの間で振り回されています。私はRSpecで公正なビットを読んで遊んだが、Shouldaではそれほどではなかった。私はShouldaの一行のアサーションを読みやすく、テストはよりきれいに見えます。しかし、Shouldaで特定のアサーションを書く方法を私が理解できないとき、私はRSpecに切り替えます。しかし、それについてはあまり幸せではありません。Rails 3カスタム検証とshoulda

これは私が今日したものです。私はモデルCourseのカスタム検証を書きました。コースにはstart_dateend_date.があります。周りにはいくつかのルールがあります。

  • start_dateend_dateは両方必須
  • start_dateは今日
  • end_dateが、私が行っている可能性がそこに静かないくつかの宝石がある知っているstart_date

前にすることはできませんよりも後にすることはできませんされていますそれは私のためです。しかし、私は新しいものだと思っています。私はそれを自分で行い、私が行くように学ぶことをお勧めします。

私が最後に書いた前に、だからこれは私のモデルは

class CourseEndDateValidator < ActiveModel::EachValidator 
    def validate_each(object, attribute, value) 
    if object.errors[attribute].blank? && object.errors[:start_date].blank? 
     if value < object.start_date 
     object.errors[attribute] << "cannot be later than start date" 
     end 
    end 
    end 
end 

class CourseStartDateValidator < ActiveModel::EachValidator 
    def validate_each(object, attribute, value) 
    if object.errors[attribute].blank? 
     if value < DateTime.now.to_date 
     object.errors[attribute] << "cannot be later than today" 
     end 
    end 
    end 
end 

し、次のように次のように

class Course < ActiveRecord::Base 
    belongs_to :category 
    has_many :batches, :dependent => :destroy 
    accepts_nested_attributes_for :batches, :reject_if => lambda {|a| a[:code].blank?}, :allow_destroy => true 
    has_and_belongs_to_many :students, :uniq => true 

    validates_presence_of :name, :course_code, :total_seats 
    validates_uniqueness_of :category_id, :scope => [:name, :course_code] 

    validates :start_date, :presence => true, :course_start_date=>true 
    validates :end_date, :presence => true, :course_end_date=>true 
end 

のような私のカスタムの検証がされているに見えるもの今私のcourse_spec

require 'spec_helper'require 'date' 

describe Course do 

    context 'validations' do 
    it { should validate_presence_of(:name)} 
    it { should validate_presence_of(:course_code)} 
    it { should validate_presence_of(:start_date)} 
    it { should validate_presence_of(:end_date)} 
    it { should validate_presence_of(:total_seats)} 

    date = DateTime.now.to_date 
    it { should allow_value(date).for(:start_date) } 
    it { should_not allow_value(date - 10).for(:start_date) } 
    it {should allow_value(date + 10).for(:end_date)} 
    end 

    context 'associations' do 
    it { should belong_to(:category)} 
    it { should have_many(:batches).dependent(:destroy)} 
    it { should have_and_belong_to_many(:students) } 
    end 

    it " end date should not be before course start date" do 
    course = FactoryGirl.build(:course, :end_date=>'2011-12-10') 
    course.should be_invalid 
    end 
end 

ですRspecを使ってブロックする "it"私の検証の文脈ではこういうことがあった

context 'validations' do 
    it { should validate_presence_of(:name)} 
    it { should validate_presence_of(:course_code)} 
    it { should validate_presence_of(:start_date)} 
    it { should validate_presence_of(:end_date)} 
    it { should validate_presence_of(:total_seats)} 

    date = DateTime.now.to_date 
    it { should allow_value(date).for(:start_date) } 
    it { should_not allow_value(date - 10).for(:start_date) } 
    it { should allow_value(date + 10).for(:end_date)} 
    it { should_not allow_value(date - 10).for(:end_date)} # <------------------- 
    end 

そしてI以下の障害

Failures: 

    1) Course validations 
    Failure/Error: it { should_not allow_value(date - 10).for(:end_date)} 
     Expected errors when end_date is set to Fri, 9 Dec 2011, got errors: ["name can't be blank (nil)", "course_code can't be blank (nil)", "total_seats can't be blank (nil)", "start_date can't be blank (nil)"] 

は、私がここで間違ってやっているかわからないですしまいました。それは私のカスタム検証コードが正しくないか、end_dateをテストするときにstart_dateがnilでないように最後のアサーションを実行する前に何かをセットアップする必要がありますか?

検証では、ビューで正常に動作します。私が入力したデータの種類に応じて正しい検証エラーを得ることを意味します。しかし、テストは失敗しています。私はこれをしばらく見てきましたが、正確に何が間違っているのか分かりません。

答えて

0

@nickgrimはすでに質問に答えていますが、コメントを追加したいと思います。 describeitのポイントは、「describe」と「it」という単語で始まる文章を奨励することです。あなたの例では、あなたはこれを持っています:

it " end date should not be before course start date" do 
    # ... 

"それは終了日...."は文ではありません。

it "validates that end date should be >= start date" do 
+0

入力していただきありがとうございますが、手順がコンソールに表示されたときに判読可能な文章にする必要がありました。私の仕様を実行するとコンソールに出力される内容は、このようなものです。 'Course 終了日はコースの開始日より前であってはなりません バリデーション は、名前を設定する必要があります course_codeを設定する必要があります。 'あなたは何ですか?スペックを読んでいる人にとって正しいと示唆している。どのアプローチを今に従うか分かりません。何かご意見は? – MMinhas

+0

私の見解では、スペックとコンソール出力を読みやすくするために作業する必要があります。しかし、あなたが冗長モードで出力を使用する場合は、両方を持つことができない場合(理由を参照してください)、コンソールの出力がより重要になります。ドットだけを使用すれば、スペックがより重要になります。しかし、私は間違いなく、テストが失敗したときに、特に読みやすいコンソール出力を見たいと思っています:) –

3

私はあなたが2次のいずれかの方法でこれに取り組むことができると思う:

あなたはbefore(:each)ブロックへにあなたのdate = DateTime.now.to_dateを配置する必要がありますいずれかのようなものとすることを記述してください。

context 'validations' do 
    before(:each) { date = DateTime.now.to_date } 

    it { should allow_value(date).for(:start_date) } 
    it { should_not allow_value(date - 10).for(:start_date) } 
    it { should allow_value(date + 10).for(:end_date)} 
    it { should_not allow_value(date - 10).for(:end_date)} 
end 

また、レールの日付ヘルパーを使用することもできます。

context 'validations' do 
    it { should allow_value(Date.today).for(:start_date) } 
    it { should_not allow_value(10.days.ago).for(:start_date) } 
    it { should allow_value(10.days.from_now).for(:end_date)} 
    it { should_not allow_value(10.days.ago).for(:end_date)} 
end 
関連する問題