【问题标题】:Unit Testing validates presence of odd behaviour单元测试验证奇怪行为的存在
【发布时间】:2012-01-24 19:45:09
【问题描述】:

我正在尝试整个 TDD,但遇到了验证存在的问题。我有一个名为 Event 的模型,我想确保在创建 Event 时存在 titlepricesummary

单元测试代码

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 失败。哪个好。 现在我想在Event 模型中使用以下代码首先让title 测试通过。

class Event < ActiveRecord::Base

  validates :title, :presence => true

end

当我重新运行测试时,我得到 3 次通过,而我认为我应该得到 1 次通过和 2 次失败。为什么我会获得 3 次通过?

【问题讨论】:

    标签: ruby-on-rails ruby unit-testing validation testing


    【解决方案1】:

    我有两个测试助手方法可以使这类事情更容易诊断:

    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
    

    这应该会显示您是否缺少预期的验证,并且还会就在预期之外失败的特定验证向您提供反馈。

    【讨论】:

      【解决方案2】:

      当您使用Event.new 创建模型时,所有属性最初的值都是nil。这意味着您正在检查的所有 3 个属性都已经为零(所以 event.title = nilevent.price = nil 实际上什么都不做)。由于 title 已标记为验证以确保其存在,除非您将 title 设置为 nil 以外的值,否则您将无法保存模型。

      也许尝试将其添加到您的测试类中:

      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? 即可避免在不需要的地方访问数据库。

      【讨论】:

      • 那么我还能如何编写这个测试来确保存在特定属性'title'、'price'、'summary'?
      猜你喜欢
      • 1970-01-01
      • 2015-02-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-21
      • 2015-12-11
      • 1970-01-01
      相关资源
      最近更新 更多