Подтвердить что ты не робот

RSpec: сопоставление массива строк по регулярному выражению

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

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

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

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

4b9b3361

Ответ 1

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

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

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

Ответ 2

Вы можете поместить следующий код в 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

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

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

Ответ 4

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

Ответ 6

Мое решение для этого похоже на @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/))

Ответ 7

Еще один вариант

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