2013-04-02 124 views
2

我正在學習RSpec,我不禁注意到我的代碼中有很多重複。以下是其他許多人的兩個例子。有沒有辦法創建一個共享測試,而不必經過每個人的屬性?如何幹燥Rails的RSpec測試

describe "validation" do 
    describe "user_id" do 
     it "should not be blank or nil" do 
     @comment.user_id = nil 
     @comment.should_not be_valid 
     @comment.user_id = " " 
     @comment.should_not be_valid 
     end 

     it "should an integer" do 
     @comment.user_id = "a" 
     @comment.should_not be_valid   
     end 
    end 

    describe "post_id" do 
     it "should not be blank or nil" do 
     @comment.post_id = nil 
     @comment.should_not be_valid 
     @comment.post_id = " " 
     @comment.should_not be_valid 
     end 

     it "should an integer" do 
     @comment.post_id = "a" 
     @comment.should_not be_valid   
     end  
    end 
    end 

回答

3

在第一個describe塊你可以設置主題爲@comment.user_id像這樣:

describe "validation" do 
    describe "user_id" do 
    before { @comment = Comment.create } # or however you want to initialize your comment  
             # (FactoryGirl is commonly used) 
    subject { @comment.user_id } 

    it "should not be blank or nil" do 
     before { @comment.user_id = nil }   #I edited this to make it clearer. 
     it { should_not be_valid } 

     before { @comment.user_id = " " } 
     it { should_not be_valid } 
    end 
    ... 

這讓它乾涸了一些,使它更具可讀性,我認爲。顯然,您可以將其餘的設置爲我在這裏的模式。


編輯:這並不挽救了許多字符(其實你打字更在最後),但它確實消除@comment.{attrbute} = whatever在規範文件本身的重複。您可以爲每個作業定義一個幫助程序,如下所示:

/spec/helpers/comment_spec_helper.rb 
def user_id nil 
    @comment.user_id = nil 
end 

.... 

然後對每個屬性執行此操作。然後在您的規格:

subject { @comment.user_id } 

    it "should not be blank" do 
     before { user_id nil }   
     it { should_not be_valid } 

    it "should not be nil" do 
    ... 

的缺點是,你必須做到這一點在助手的每個屬性,你到底在做一點更多的工作。但是,如果您的主要擔心是消除spec文件中的重複,這將有所幫助。

我不知道這是多麼地道。我通常會在spec文件中啓動新的對象以進行驗證測試(我的spec_helper通常會處理多個步驟的流程,例如點擊下拉菜單,填充文本,然後單擊「提交」),但是可能比我通常具有更多的驗證。


UPDATE

我工作的一個項目,只是通過從Codeschool的RSpec的過程中,我做了筆記翻轉,我想我會建議共享的例子。他們給出的例子是:

describe Zombie do 
    it_behaves_like ‘the undead’, Zombie.new 
end 

describe Vampire do 
    it_behaves_like ‘the undead’, Vampire.new 
end 

shared_examples_for ‘the undead’ do |undead| 
    it ‘does not have a pulse’ do 
    undead.pulse.should == false 
    end 
end 

這似乎是適用的,但你必須記住某些conventions,以確保您的共享實例被加載。

這真的會幹掉你的代碼,但我個人會對可讀性有點擔心。我想如果你使用描述性足夠的名字作爲共享的例子,你會沒事的。

+0

一個改進,但沒有我希望的那麼多。我只是'example_groups',但我不確定它們是否可以在這種情況下使用。 – dee

+0

我剛剛添加了一些關於'shared_examples'的內容,然後搜索了'example groups',以發現它們是相同的。 D'哦!無論如何,我認爲他們當然可以在上下文中使用。 – aceofbassgreg

+0

這適用於對象的實例變量嗎?假設你想爲'foreign_keys'創建'shared_examples',不應該是'nil'或'blank',你會如何動態地將密鑰傳遞給共享示例?你給的例子傳遞了一個完整的對象:'Vampire.new' – Mohamad

1

你可以使用的工廠(如FactoryGirl):

build(:comment, user_id: nil).should_not be_valid