我現在在Shoulda和Rspec之間搖擺。我已經閱讀並且在RSpec上播放了一些,但與Shoulda沒有多大關係。我發現Shoulda的一行斷言更容易閱讀,測試看起來更清晰。但是當我無法弄清楚在Shoulda中如何編寫特定的斷言時,我將切換到RSpec。雖然不是很高興。Rails 3自定義驗證和shoulda
所以這就是我今天所做的。我爲我的模型Course
寫了一些自定義驗證。一個課程有一個start_date
和一個end_date.
有一些規則。
start_date
和end_date
都是強制性start_date
不能遲於今天end_date
不能前start_date
我知道有安靜的幾個寶石,在那裏,可以做它對我來說。但是,因爲我是新的,我認爲這可能是一個好主意,我自己做,並隨着我的學習而去學習。
所以這是我的模型是什麼樣子
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
我的自定義校驗都是如下
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
而以下是我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我在我的驗證上下文中有這樣的東西
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
而且我得到了以下故障
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不爲零?
驗證在視圖中正常工作。我的意思是,根據我輸入的數據類型,我得到了正確的驗證錯誤。但是我的測試失敗了。我一直在看這一段時間,但無法弄清楚我到底做錯了什麼。
感謝您的輸入,但我認爲當在控制檯上打印出步驟時,他們應該做出可讀的句子。所以當我運行我的規範時,我的輸出是這樣的'課程 結束日期不應該在課程開始日期 驗證 應該要求名稱設置 應該要求設置course_code ... '你是什麼這對於閱讀規範的人來說是正確的。我不確定現在採用哪種方法。有什麼想法嗎? – MMinhas 2011-12-19 22:57:15
從我的角度來看,我們應該努力使規格和控制檯輸出可讀。但是,如果你不能同時使用輸出(請參閱爲什麼),那麼如果以詳細模式使用輸出,控制檯的輸出更重要。如果你只使用點,那麼規範更重要。但我絕對想看到一個好的可讀控制檯輸出,特別是當測試失敗時:) – 2013-10-22 15:41:00