【问题标题】:How to test a model validation with a regex in RSpec?如何在 RSpec 中使用正则表达式测试模型验证?
【发布时间】:2016-10-15 16:34:24
【问题描述】:

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

型号

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

【问题讨论】:

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


    【解决方案1】:

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

    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)中的范围,但不太可能有人会编写错误的代码包括那些字符,所以我不会走那么远。

    【讨论】:

    • 我想测试所有正则表达式模式不匹配的情况。我不确定这是否能解决这个问题,因为它只测试特定情况。您确实为我确定了随机字符选择器是真实的,因为它可能会在给定的测试运行期间选择通过但在其他测试运行期间不通过的结果。我想知道我是否应该将其分解为多个测试,以查找所有符号、所有数字之类的东西......
    • 再一次,你不能真正测试所有的负面案例;太多了。问题是编写下一个测试是否会激励您更改代码。我只是添加了两个测试:我意识到我没有强制正则表达式有范围。测试 z 和 9 并不会阻止您编写只匹配 a、z、0 和 9 的正则表达式,但不太可能有人会这样做,所以我不会测试更有效的案例。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-30
    • 2014-10-21
    • 2023-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多