除非另一个字段是真正的rails,如何测试验证状态?

时间:2015-07-09 07:11:46

标签: ruby-on-rails ruby validation rspec dry

鉴于此代码:

field :start_now, type: Boolean, :default => true
field :time_zone
validates :time_zone, inclusion: { 
              in: ActiveSupport::TimeZone.zones_map.keys 
           }, unless: :start_now?

我已经创建了这个rspec测试,但它很长而不是DRY。而这样的唯一原因是因为"除非"条件:

describe "#time_zone" do
  context "scheduled" do
    before :each do
       subject.start_now = false
    end
    it { is_expected.to validate_inclusion_of(:time_zone).in_array(ActiveSupport::TimeZone.zones_map.keys) }
  end
  context "run now" do
    before :each do
       subject.start_now = true
    end
    it { is_expected.not_to validate_inclusion_of(:time_zone).in_array(ActiveSupport::TimeZone.zones_map.keys) }
  end
end

有没有更短的方法呢?

3 个答案:

答案 0 :(得分:1)

确实没有必要让它更短。这两项测试都准确描述了他们正在测试的内容,并且他们非常具体关于这些测试。

从我在测试中看到的情况来看,您希望测试成为DAMP。这并不意味着他们不会干,但 意味着你不应该向后弯曲以使其尽可能小而窄。

您的代码有两个不同且互斥的状态,这取决于布尔值start_now?。你必须测试这两种状态,而且真的没有办法解决这个问题。也没有重复;你正在测试两个不同的分支。

在您的上下文could use a wee bit of a verbiage clean up中,他们非常擅长描述您需要做的事情。

答案 1 :(得分:1)

这里和改进。下一个代码更干,同时比以前更多DAMP:

describe "#time_zone" do    
  let(:validate_time_zone) { validate_inclusion_of(:time_zone).in_array(ActiveSupport::TimeZone.zones_map.keys }

  context "scheduled" do
    before :each do
       subject.start_now = false
    end
    it { is_expected.to validate_time_zone }
  end
  context "run now" do
    before :each do
       subject.start_now = true
    end
    it { is_expected.not_to validate_time_zone}
  end
end

好的,所以我明白DAMP(对我来说是一个新词)是好的。我今天感觉好多了,因为我一直在考虑过度干燥测试并使它们难以阅读的问题。

答案 2 :(得分:1)

有时我喜欢使用外部let中调用的每个上下文中的before :each编写我的规范。这样可以避免为每个上下文重复before :each

describe "#time_zone" do    
  let(:validate_time_zone) do
    validate_inclusion_of(:time_zone).in_array(ActiveSupport::TimeZone.zones_map.keys
  end

  before :each do
    subject.start_now = start_now
  end

  context "scheduled" do
    let(:start_now) { false }
    it { is_expected.to validate_time_zone }
  end

  context "run now" do
    let(:start_now) { true }
    it { is_expected.not_to validate_time_zone}
  end
end