2011-09-24 24 views
66

Rails'deki TDD ile yolculuğuma başladım ve bir çözüm bulmayacağım model doğrulama testleri ile ilgili küçük bir soruna girdim. , I bir kullanıcı modeli var demekRaylar 3.1, RSpec: test modeli doğrulamaları

class User < ActiveRecord::Base 
    validates :username, :presence => true 
end 

edelim ve basit bir test

it "should require a username" do 
    User.new(:username => "").should_not be_valid 
end 

Bu doğru varlığı doğrulama testleri, ama daha belirgin olmak ne isterseniz? Örneğin, hatalarda test full_messages nesne .. İlk denemede (should_not be_valid kullanarak) hakkında

it "should require a username" do 
    user = User.create(:username => "") 
    user.errors[:username].should ~= /can't be blank/ 
end 

Benim endişe RSpec açıklayıcı hata mesajı üretmez olacaktır. Basitçe "beklenen geçerli? Yanlış dönmek, doğru" diyor. Ancak, ikinci test örneğinin küçük bir dezavantajı vardır: hata nesnesine ulaşmak için yeni yöntem yerine oluşturma yöntemini kullanır.

Testlerimin neyi test ettikleri konusunda daha spesifik olmasını isterim, aynı zamanda bir veritabanına dokunmak zorunda kalmam.

Herhangi bir girdi var mı?

cevap

91

İlk önce size kötü bir adınız olduğunu söylemek isterim.

İKİNCİ, TEŞVİKLERİNDEN DOĞRU TEŞVİK EDİYORUZ.

en basit, hızlı ve kirli çözüm bu gibi testlerin her önce yeni geçerli bir model oluşturmak için olacaktır:

before(:each) do 
    @user = User.new 
    @user.username = "a valid username" 
end 

AMA ne önermek bir üretecektir tüm modelleri için fabrikalar kurmak olduğunu Otomatik olarak sizin için geçerli bir model ve daha sonra bireysel özniteliklerle kaynaşabilir ve doğrulama işleminin yapılıp yapılamayacağını görebilirsiniz. Böyle bir şey olmazdı testinizi kurmak için Temelde bir kez

: Bunun için FactoryGirl kullanmak ister

it "should have valid factory" do 
    FactoryGirl.build(:user).should be_valid 
end 

it "should require a username" do 
    FactoryGirl.build(:user, :username => "").should_not be_valid 
end 

ya Oh ve burada benden daha hepsini iyi açıklayan a good railscast geçerli:

iyi şanslar :)


GÜNCELLEME: fabrika kız için sözdizimi vardır version 3.0 itibariyle değişti. Bunu yansıtmak için örnek kodumu değiştirdim.

+2

Çok teşekkürler Matthew. Test etmeye çalıştığım hataya yaklaşmanın bir yolu var mı? X.should_not be_valid bana çok benzer görünüyor ve yolun aşağısındaki bir şeyin kaydı geçersiz kılacağını bilen var. Bu test daha sonra yanlış noktada başarısız olur. Bu arada, cevabınızı kabul edildi olarak işaretlediğimi düşünüyorum. Ben yapmadım – Feech

+7

Doğru, bu yüzden fabrikalar için tartışıyorum. Tek bir yerde geçerli bir kullanıcı üretmek için kodu yazarsınız ve daha sonra, onu geçersiz kılacağınızdan emin olmak için tüm bireysel testlerden önce geçerli olduğundan emin olmak için bir test yazarsınız. Bu sebepten dolayı modelinizi değiştirdiğinizde modelinizi daha uzun süre fabrikada geçerli bir kullanıcı üretir. Factory.build (: user) .should be_valid' test başarısız olur ve fabrikanızı güncellemeniz gerektiğini bileceksiniz ... ? (ve evet benim 7 cevabı kabul ettiniz) – Matthew

+0

Kusursuz bir açıklama. Tekrar teşekkürler. – Feech

41

Model doğrulamaları (ve daha çok etkin kayıt) test etmenin daha kolay bir yolu, shoulda veya remarkable gibi bir mücevher kullanmaktır.

Bunlar aşağıdaki gibi teste izin verir: özellik veya talep gözlük

describe User 

    it { should validate_presence_of :name } 

end 
+1

Bu, modellerde ilişkilendirmelere sahip olduğunuzu kontrol etmekte fayda var, ancak bir isim olmadan bir kullanıcı oluşturmaya çalışmadığını ve geçerliliğini kontrol etmediğinin farkında olmalısınız – brafales

+3

Aslında hayır, afaik tam olarak ne yapıyor? Nesneyi boş bir adla oluşturmaya çalışacak ve bir hata vermelidir. – nathanvda

+2

Haklısınız, kodu yanlış okumuşum gibi görünüyor https://github.com/thoughtbot/shoulda-matchers/blob/master/lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb – brafales

0

Ben geleneksel olarak ele sahip hata içerik gözünden.Yani, örneğin, ben aşağıda yoğunlaşmasına edeceğiz benzer spec var: Öyleyse

Özelliği Spec Örnek

before(:each) { visit_order_path } 

scenario 'with invalid (empty) description' , :js => :true do 

    add_empty_task         #this line is defined in my spec_helper 

    expect(page).to have_content("can't be blank") 

, o zaman benim bir şey geçerli olup olmadığını benim modeli Spec test var, ama Hata mesajının tam çıktısını test eden özellik özellikleri. FYI, bu özellik özellikleri here bulunabilir Capybara gerektirir.

15

bu deneyin: Yeni sürüm RSpec içinde

it "should require a username" do 
    user = User.create(:username => "") 
    user.valid? 
    user.errors.should have_key(:username) 
end 
+0

Bu benim en sevdiğim, çok katı, anahtarını denetler ve iletiyi değil, bir detay olan – ecoologic

+3

sadece kullanıcı = User.new kullanabilirsiniz (: kullanıcıadı => "") db'ye izin vermemek için –

+0

@TaufiqMuhammadi 'new' db düzeyinde doğrulamaları vurmayacaktır, örneğin teklik endeksi kısıtlaması. – mnort9

2

, sen yerine olmalıdır bekliyoruz kullanmalısınız aksi takdirde alırsınız uyarı: @nathanvda Dediğim gibi

it "should have valid factory" do 
    expect(FactoryGirl.build(:user)).to be_valid 
end 

it "should require a username" do 
    expect(FactoryGirl.build(:user, :username => "")).not_to be_valid 
end 
+0

Örnek isimlerinde değil, şimdiki zaman fiillerini de kullanmalısınız. Yukarıdakiler "geçerli bir fabrikaya sahiptir" ve "kullanıcı adı gerektirir" şeklinde yeniden yazılabilir. – BrunoFacca

0

, ben yararlanmak istiyorum Thoughtbot'un Shoulda Matchers gem. Bu sallanmada, testinizi varlığını ve özel bir hata mesajını test etmek için aşağıdaki şekilde yazabilirsiniz.

RSpec.describe User do 

    describe 'User validations' do 
    let(:message) { "I pitty da foo who dont enter a name" } 

    it 'validates presence and message' do 
    is_expected.to validate_presence_of(:name). 
     with_message message 
    end 

    # shorthand syntax: 
    it { is_expected.to validate_presence_of(:name).with_message message } 
    end 

end