RSpec: сопоставить массив строк по регулярному выражению - PullRequest
13 голосов
/ 10 ноября 2010

Я проверяю проверку моих моделей с помощью rspec и ожидаю сообщение об ошибке.Однако точный текст сообщения, скорее всего, изменится, поэтому я хочу быть немного более прощающим и проверять только частичное сообщение.

Поскольку метод Spec :: Matchers :: include работает только для строк и коллекций, в настоящее время я использую эту конструкцию:

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

Это работает, но мне кажется немного громоздким.Есть ли лучший (т. Е. Более быстрый или более похожий на ruby) способ проверки массива на наличие строки с помощью регулярных выражений или, возможно, соответствия rspec, который делает именно это?

Ответы [ 7 ]

16 голосов
/ 08 сентября 2012

Я бы порекомендовал сделать

@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/
   +"[]"

Таким образом, вы можете увидеть причину неудачи, и вам не нужно много копаться, чтобы выяснить, почему она терпит неудачу.

11 голосов
/ 15 сентября 2014

Использование RSpec 3 expect синтаксиса с сопоставителями, составляющими :

Для соответствия всем:

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/
9 голосов
/ 03 августа 2013

Вы можете поместить следующий код в 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}
8 голосов
/ 10 ноября 2010

Не думаю, что это влияет на производительность, но более RSpec-подобное решение было бы

@user.errors[:password].should be_any { |m| m =~ /is too short/ }
6 голосов
/ 21 июня 2013

Оба приведенных выше ответа хороши.Однако я бы использовал более новый синтаксис 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

3 голосов
/ 16 января 2014

Мое решение этого похоже на @ muirbot's.Я использую пользовательские сопоставления.Тем не менее, я использую реальное совпадение 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/))
0 голосов
/ 25 декабря 2013

Просто еще один вариант

@user.errors[:password].grep /is too short/
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...