RSpec:通过正则表达式匹配字符串数组

时间:2010-11-10 15:26:26

标签: ruby-on-rails ruby rspec

我正在使用rspec测试我的模型的验证,并期待一条错误消息。但是,消息的确切文本可能会发生变化,所以我想要更宽容一些,只检查部分消息。

由于Spec :: Matchers :: include方法仅适用于字符串和集合,我目前正在使用此构造:

@user.errors[:password].any?{|m|m.match(/is too short/)}.should be_true

这可行,但对我来说似乎有点麻烦。是否有更好的(即更快或更像红宝石)的方法来检查数组是否包含正则表达式的字符串,或者可能是这样做的rspec匹配器?

7 个答案:

答案 0 :(得分:16)

我建议你做

@user.errors[:password].to_s.should =~ /is too short/

只是因为它会在失败时给你一个更有帮助的错误。如果您使用be_any,那么您会收到这样的消息......

Failure/Error: @user.errors[:password].should be_any{ |m| m =~ /is too short/}
    expected any? to return true, got false

但是,如果您使用to_s方法,那么您将获得以下内容:

 Failure/Error: @user.errors[:password].to_s.should =~ /is too short/
   expected: /is to short/
        got: "[]" (using =~)
   Diff:
   @@ -1,2 +1,2 @@
   -/is too short/
   +"[]"

所以你可以看到失败的原因,而不必去挖掘它为什么会失败。

答案 1 :(得分:11)

RSpec 3 expect syntaxmatchers composing一起使用:

匹配所有:

expect(@user.errors[:password]).to all(match /some message/)

匹配任何:

expect(@user.errors[:password]).to include(match /some message/)
expect(@user.errors[:password]).to include a_string_matching /some message/

答案 2 :(得分:9)

您可以将以下代码放在spec / support / custom_matchers.rb

RSpec::Matchers.define :include_regex do |regex|
  match do |actual|
    actual.find { |str| str =~ regex }
  end
end

现在您可以像这样使用它:

@user.errors.should include_regex(/is_too_short/)

并确保在spec / spec_helper.rb

中有类似的内容
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}

答案 3 :(得分:8)

我认为它不会产生性能差异,但是更像RSpec的解决方案

@user.errors[:password].should be_any { |m| m =~ /is too short/ }

答案 4 :(得分:6)

以上两个答案都很好。但是,我会使用较新的Rspec expect语法

@user.errors[:password].to_s.should =~ /is too short/

成为

expect(@user.errors[:password].to_s).to match(/is too short/)

此处有更多精彩信息:http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax

答案 5 :(得分:3)

我对此的解决方案与@ muirbot相似。我使用自定义匹配器。但是,我使用真正的include匹配器,但使用自定义匹配器作为参数进行扩充。在套件运行之前加载它(例如在spec / support / matchers.rb中,依次由spec / spec_helper.rb加载):

RSpec::Matchers.define(:a_string_matching) do |expected|
  match do |actual|
    actual =~ expected
  end
end

然后你的期望可以这样写:

expect(@user.errors[:password]).to include(a_string_matching(/is too short/))

答案 6 :(得分:0)

只是另一种选择

@user.errors[:password].grep /is too short/