如何在RSpec中使用正则表达式测试模型验证?

时间:2016-06-14 19:29:49

标签: ruby-on-rails ruby regex rspec rspec-rails

经过一些黑客攻击后,我提出了以下测试,以确保我的模型验证器上的正则表达式模式正常工作。我想知道是否有更好的方法来测试这些条件而不是构建一个坏字符串。我想说明批准的正则表达式模式之外的任何和所有字符。不同的列也可能具有不同的验证器。

模型

validates :provider_unique_id,
           presence: true,
           length: { maximum: 50 },
           format: { with: /\A[A-Za-z0-9]+\z/ }

规格

describe 'provider unique id' do
  let(:bad_string) { (0..255).map(&:chr).select { |x| x != /\A[A-Za-z0-9]+\z/ }.sample(20).join }

  it 'should exist' do
    shop.provider_unique_id = nil
    expect(shop.valid?).to be_falsey
  end

  it 'passes regex rules' do
    shop.provider_unique_id = bad_string
    expect(shop.valid?).to be_falsey
  end
end

1 个答案:

答案 0 :(得分:0)

如果我是非常彻底的话,这就是我写的东西。想象一下,测试驱动验证,一次添加一个测试并添加验证以使其通过。

describe '#provider_unique_id' do
  %w(a z).each do |letter|
    it "can be letter #{letter}" do
      expect_to_be_valid letter
    end
  end

  # after making this pass, I'd change the regex to use the i flag so I wouldn't need to test for Z
  it "can be uppercase" do
    expect_to_be_valid 'A'
  end

  [0, 9].each do |digit|
    it "can be digit #{digit}" do
      expect_to_be_valid digit
    end
  end

  it "can be more than one character" do
    expect_to_be_valid '00'
  end

  it "isn't nil" do
    expect_to_be_invalid nil
  end

  it "isn't blank" do
    expect_to_be_invalid ""
  end

  it "can be 50 characters long" do
    expect_to_be_valid('0' * 50)
  end

  it "can't be longer than 50 characters" do
    expect_to_be_invalid('0' * 51)
  end

  # I chose _ as a non-alphanumeric since it's the only non-alphanumeric word character.
  # That is, it's as close to a valid character as it can be without be valid.
  it "can't contain a non-alphanumeric character" do
    expect_to_be_invalid '_'
  end

  # this example forces you to add \A
  it "can't begin with a non-alphanumeric character" do
    expect_to_be_invalid '_0'
  end

  # this example forces you to add \z
  it "can't end with a non-alphanumeric character" do
    expect_to_be_invalid '0_'
  end

  def expect_to_be_valid(provider_unique_id)
    shop.provider_unique_id = provider_unique_id
    expect(shop).to be_valid
  end

  def expect_to_be_invalid(provider_unique_id)
    shop.provider_unique_id = provider_unique_id
    expect(shop).to_not be_valid
  end

end

我不会随机生成错误的字符串,因为它不会强迫您编写任何其他代码。我认为使用_的测试就足够了。请注意,还有比ASCII 0-255更多的字符,测试它们是不切实际的。

您可以通过测试每个范围之前和之后的字符来想象边界检查正则表达式中的范围(a-zA-Z0-9),但它是不太可能有人会编写错误地包含这些字符的代码,所以我不会那么远。