2010-11-10 19 views
12

Modellerimin rspec ile doğrulanmasını test ediyorum ve bir hata iletisi bekliyorum. Bununla birlikte, mesajın tam metni değişebilir, bu yüzden biraz daha affedici olmak istiyorum ve sadece kısmi bir mesajı kontrol ediyorum. Spec :: matchers yana RSpec: Bir dizi diziyi regex ile eşleştirin

::

yöntem yalnızca, Şu anda bu yapıyı kullanıyorum dizeleri ve koleksiyonları için çalışır şunlardır:

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

Bu ancak işler benim için hantal biraz görünüyor. Bir dizginin regex'e eklenmesi için bir dizi ya da belki de bunu yapan bir rspec eşleştirici için bir dizi kontrol etmek daha iyi (yani, daha hızlı ya da daha yakut gibi) bir yolu var mı?

+2

Özel bir eşleştirici yapın – shingara

cevap

16

Ben

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

Basitçe yapıyor öneriyoruz olurdu başarısız olduğunda yararlı hata. Eğer be_any kullanırsanız o zaman, Ancak ...

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

şöyle bir ileti almak sonra to_s metodu verirken, böyle bir şey alacak:

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

Yani sebebini görebilirsiniz başarısızlık için ve neden başarısız olduğunu anlamak için çok kazmaya gerek yok.

+0

Bu, her zaman kullandığım sürüm ve iyi çalışıyor. 'Be_any' – nzifnab

8

Ben bir performans farkı yaratan sanmıyorum ama bir daha RSpec benzeri çözüm size daha verecek çünkü

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

Çok daha güzel, teşekkürler. Şimdi sadece be_any için belgeler bulabilirsem ... – Thilo

+0

Dokümanlar için, http://rubydoc.info/gems/rspec-expectations/2.0.1/frames adresini ziyaret edin. “be_any”, “Enumerable” dan gelen “any” 'yükleminden dinamik olarak üretilir. – zetetic

+0

"Herhangi biri" nin "be_any" ye nasıl dönüştüğünü görebiliyorum ama iyi İngilizce gibi gelmiyor. –

9

Sen Spec/destek/custom_matchers.rb aşağıdaki kodu koyabilirsiniz

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

Şimdi bunu şöyle kullanabilirsiniz:

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

ve Spec/spec_helper.rb

Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f} 
+0

En İyi yanıtı kullandığınızda belirsiz hata mesajından neyin yanlış gittiğini anlamanın zorluğuna katılıyorum. Teşekkürler! –

0

Bir başka seçenek de böyle bir şey var emin olun

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

Buna Çözümümün @ muirbot en benzer. Özel bir eşleştirici kullanıyorum. Ancak, gerçek include eşleştiriciyi kullanıyorum, ancak özel bir eşleştirici ile bir argüman olarak genişletin. Paketinizi çalıştırmadan önce bir yere yükleyin (örneğin, spec/support/matchers.rb dosyasında spec/spec_helper tarafından yüklendi).rb):

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

Sonra beklenti böyle yazılabilir:

eşleştirmek için tüm:

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

herhangi eşleştirmek için

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

'a_string_matching' [zaten RSpec'in bir parçasıdır] (https://github.com/rspec/rspec-expectations/blob/3b8d6a55d75d02039f3b95555690d9f987da1f82/lib/rspec/matchers.rb#L677) böylece tanımlamaya gerek yoktur. Oluşturucu eşleştiriciler RSpec 3.0 –

5

RSpec 3 expect syntaxmatchers composing ile kullanma:

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

'dan destekleniyor. Bu doğru değil. Dizinle eşleştirmek için en az bir ** şifre hatası ** istiyorum, ancak mutlaka ** hepsi **. – Thilo

+0

Benim hatam. Daha sonra, (@ user.errors [: password]) bekleyiniz. (Eşleme/bazı mesajlar /) 'veya daha da iyisi' beklemek (@ user.errors [: password]) a_string_matching/some message/' –