2011-09-03 60 views
1

假設我有一個實例方法,可以執行許多不同的事情,我需要測試它們,比如store#process_order。我想測試它發送給客戶的電子郵件,在訂單表中添加一個條目,向信用卡收取費用等。在rspec中設置此值的最佳方法是什麼?目前,我使用rspec和工廠女孩我做這樣的事情:在rspec中用多個「it」塊設置一個測試

describe Store do 
    describe "#process_order" do 
    before do 
     @store = Factory(:store) 
     @order = Factory(:order) 
     # call the process method 
     @store.process_order(@order) 
    end 

    it 'sends customer an email' do 
     ... 
    end 
    it 'inserts order to db' do 
     ... 
    end 
    it 'charges credit card' do 
     ... 
    end 
    end 
end 

但它感覺真的很乏味。這真的是寫一個規範的正確方法,我需要確保做幾件不同的事情嗎?

注:我對這個設計是否優秀並不感興趣。這只是我爲彌補我的問題而編寫的一個例子 - 如何編寫這些類型的規格。

+0

如果它做了幾件不同的事情,你應該做幾個不同的測試。 DRY不是一個規則! – Eric

回答

1

我認爲你在做什麼很好,我認爲這是rspec打算使用的方式。每個有關您的應用程序的聲明(規範)都有自己的塊。

您可能會考慮使用before (:all) do,以便訂單隻需要處理一次,但這可能會引起規格運行順序的依賴關係。

如果需要,您可以將describe "#process_order"中的所有代碼合併到一個大的it塊中,但是這樣會降低可讀性,並且rspec在規範失敗時會給您提供的有用錯誤消息較少。去頭,並添加raise到您的測試之一,看看你可以從rspec得到一個很好的錯誤消息,如果你這樣做,你現在正在做它。

2

這是一種很好的方法,因爲您可以確定哪些元素在未來發生中斷時會被破壞。我全都是爲了單獨測試。我傾向於不檢查插入到數據庫中的東西,因爲你是軌道功能。我只是簡單地檢查對象的有效性。

這也是在RSpec書中使用的方法。如果您不確定與RSpec相關的任何事情,我肯定會推薦閱讀它。

1

如果你想測試整個過程,那麼我們正在談論一個集成測試,而不是單元測試。如果你想測試#process_order 方法它做了幾件事情,那麼我希望這些事情意味着調用其他方法。所以,我會添加#should_receive期望並確保覆蓋所有路徑。然後我會分別指定所有這些方法,所以我有一個很好的單元規格套件。最後,我肯定會寫一個集成/驗收規範,檢查所有這些部分是否一起工作。

此外,我會使用#let來設置刪除規範示例(它阻止)之間的依賴關係的測試對象。否則,其中一個示例的失敗可能會導致其他示例中的錯誤給您提供不正確的反饋。