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

Thi*_*ilo 14 ruby rspec ruby-on-rails

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

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

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

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

rad*_*und 17

我建议做

@user.errors[:password].to_s.should =~ /is too short/
Run Code Online (Sandbox Code Playgroud)

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

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

但是,如果您使用该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/
   +"[]"
Run Code Online (Sandbox Code Playgroud)

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


Mac*_*ski 13

使用RSpec 3 expect语法匹配器组合:

要匹配所有:

expect(@user.errors[:password]).to all(match /some message/)
Run Code Online (Sandbox Code Playgroud)

匹配任何:

expect(@user.errors[:password]).to include(match /some message/)
expect(@user.errors[:password]).to include a_string_matching /some message/
Run Code Online (Sandbox Code Playgroud)


mui*_*bot 9

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

RSpec::Matchers.define :include_regex do |regex|
  match do |actual|
    actual.find { |str| str =~ regex }
  end
end
Run Code Online (Sandbox Code Playgroud)

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

@user.errors.should include_regex(/is_too_short/)
Run Code Online (Sandbox Code Playgroud)

并确保您在spec/spec_helper.rb中有类似的内容

Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
Run Code Online (Sandbox Code Playgroud)


mik*_*ber 8

I don't think it makes a performance difference, but a more RSpec-like solution would be

@user.errors[:password].should be_any { |m| m =~ /is too short/ }
Run Code Online (Sandbox Code Playgroud)


Nea*_*eal 6

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

@user.errors[:password].to_s.should =~ /is too short/
Run Code Online (Sandbox Code Playgroud)

expect(@user.errors[:password].to_s).to match(/is too short/)
Run Code Online (Sandbox Code Playgroud)

这里有更多信息:http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax