2012-01-24 71 views
2

我正在嘗試整個TDD,並且遇到了驗證存在的問題。我有一個名爲Event的模型,我想確保當創建title a pricesummary時存在Event單元測試驗證是否存在奇怪的行爲

單元測試代碼

class EventTest < ActiveSupport::TestCase 

    test "should not save without a Title" do 
    event = Event.new 
    event.title = nil 
    assert !event.save, "Save the Event without title" 
    end 

    test "should not save without a Price" do 
    event = Event.new 
    event.price = nil 
    assert !event.save, "Saved the Event without a Price" 
    end 

    test "should not save without a Summary" do 
    event = Event.new 
    event.summary = nil 
    assert !event.save, "Saved the Event without a Summary" 
    end 

end 

運行測試,我得到3失敗。哪個好。 現在我想要title測試通過Event模型中的以下代碼首先通過。

class Event < ActiveRecord::Base 

    validates :title, :presence => true 

end 

當我重新運行測試,我得到3次,我會覺得我應該得到1 PASS和2失敗。爲什麼我得到3個通行證?

回答

2

我有兩個測試輔助方法,可以讓這種事情更容易診斷:

def assert_created(model) 
    assert model, "Model was not defined" 
    assert_equal [ ], model.errors.full_messages 
    assert model.valid?, "Model failed to validate" 
    assert !model.new_record?, "Model is still a new record" 
end 

def assert_errors_on(model, *attrs) 
    found_attrs = [ ] 

    model.errors.each do |attr, error| 
    found_attrs << attr 
    end 

    assert_equal attrs.flatten.collect(&:to_s).sort, found_attrs.uniq.collect(&:to_s).sort 
end 

你會使用它們的情況下是這樣的:

test "should save with a Title, Price or Summary" do 
    event = Event.create(
    :title => 'Sample Title', 
    :price => 100, 
    :summary => 'Sample summary...' 
) 

    assert_created event 
end 

test "should not save without a Title, Price or Summary" do 
    event = Event.create 

    assert_errors_on event, :title, :price, :summary 
end 

這應該表明,如果你錯過了您期望的驗證,並且還會向您提供有關未預期的失敗的特定驗證的反饋。

+1

這工作得很好。感謝幫手。 – alenm

1

當您使用Event.new創建模型時,所有屬性最初的值爲nil。這意味着你正在檢查的所有3個屬性都是零(所以event.title = nilevent.price = nil實際上並沒有做任何事情)。由於title已被標記爲驗證以確保其存在,除非您將title設置爲零以外的值,否則將無法保存模型。

也許你可以添加以下到您的測試類:

setup do 
    @event_attributes = {:title => "A title", :price => 3.99, :summary => "A summary"} 
end 

然後,而不是:

event = Event.new 
event.title = nil 

用途:

event = Event.new(@event_attributes.merge(:title => nil)) 

做所有的測試相同的(代:title與你正在驗證存在的任何屬性)

此外,沒有理由撥打save來測試有效狀態。您可以撥打event.valid?以避免在不需要的情況下前往數據庫。

+0

那麼我該怎麼寫這個測試以確保特定屬性的'title','price','summary'存在? – alenm

+0

查看編輯答案 – PinnyM

相關問題