2009-06-25 60 views
3

我試圖提高我的TDD/OO技能,並且每次嘗試使用TDD來影響設計時,我都會碰到從哪裏開始的牆。用TDD思考OO - 從哪裏開始?

這裏是我的使用案例/故事:

找出到期複審客戶的一個子集。爲他們開始審查併發送幾封信。

現在我的肌肉記憶已經打開了一個查詢窗口,編寫了查詢,設計了一個UI,然後我必須編寫一些代碼將這些位粘合在一起。

我希望域代碼成爲焦點,我希望它在測試中。

那麼在這種情況下最簡單的事情是什麼?

我想我想要我的客戶名單。我已經有了一個客戶端對象(CSLA風格),儘管這有一個很難破解的依賴關係。我想我可以有一個ClientReviewClients對象,並測試我得到正確數量的評論。我需要考慮的因素有很多,所以看起來並不簡單。無論如何,我如何嘲笑20個客戶中有10條評論的事實?

任何人都可以在我的路上幫助我嗎?

回答

4

這裏 - 我會在您關閉了幾個測試:

class IdentifyClientsDueForReview { 
    public void CanStartSearch() { 
     var s = new ClientSearcher(); 
    } 

    public void CanSearchClients() { 
     var s = new ClientSearcher(); 
     var r = s.Find(c => c.Id == 1); 
     Assert.IsNotNull(r); 
    } 

    public void Finds10Clients() { 
     var db = new MockDB(); 
     // Clients that need review 
     for (int i = 0; i < 10; i++) { 
     db.Add(new Client() { 
      NextReview = DateTime.Today.SubtractDays(i) 
     }); 
     } 
     // Clients that don't need review 
     for (int i = 0; i < 10; i++) { 
     db.Add(new Client() { 
      NextReview = DateTime.Today.AddDays(i) 
     }); 
     } 

     var s = new ClientSearcher(db); 
     var r = s.Find(c => c.NextReview <= DateTime.Today); 
     Assert.AreEqual(10, r.Count); 
    } 
} 

這是用的LINQ to SQL或考慮類似的後端ORM建 - 否則,你可能溝Find方法有一些硬編碼FindBy<Criteria>方法。

這應該給你ClientSearcher類,它使用一個接口來命中數據庫。 MockDBRealDB類都將實現該接口。

+0

有很多東西在那裏。一個類來搜索客戶。我想我會把它放在像客戶對象這樣的神。 – 2009-06-25 11:35:50

+0

CanStartSearch在那裏做什麼沒有斷言? – 2009-06-25 14:15:45

+0

@約翰 - 沒有什麼。通過創建課程讓你成爲第一個綠色欄。 – 2009-06-25 14:39:56

1

單元測試必須快。如果一個測試涉及到數據庫,這是一個集成測試(這也是有價值的),而不是單元測試。

至於需要審覈的客戶數量,我不會特別感興趣知道我有20個需要審覈,但對於特定的客戶,我是否正確地決定客戶是否需要審覈根據我的業務規則進行審查?

您可能會發現這兩個部分組成的系列 「TDD /使用與CSLA.Net Mock對象」 有所幫助:

你提到的困難依賴關係,我強烈建議與Michael Feathers的遺留代碼有效地工作。本書充滿conservative dependency-breaking techniques有用於帶來測試代碼。

1

我不熟悉C#,所以我不能幫你解決模擬問題,我想這取決於你的測試框架。

雖然我做了很多TDD,但通常我的方法是自上而下的方法。我首先想到了我想寫的代碼來做些什麼。可以說在你的例子中,我有一個類客戶端,並希望能夠做一些事情,如:Client.initiate_reviews

因此,我寫一個測試,設置上下文(幾個客戶端,一些評論)。然後調用Client.initiate_reviews,然後寫出所有斷言,以確定它是否已完成其工作,即對於要檢查的客戶端子集,現在是否有正在進行的審覈,並且是否預期發送?

根據一個方法有多少副作用,在多個測試中分解它可能是謹慎的。

然後我進入客戶端類並定義方法並考慮想要寫入的代碼。也許是這樣的:

clients = Client.find_all_due_for_review 
for_each client in clients { 
    review = Review.start_new_for(client) 
    Letter.send_for_review(review) 
} 

然後我會寫這個方法中調用的方法的測試,我必須實現。 find_all_due_for_review沒有副作用,但返回一些東西,所以當然你會在這裏測試返回值,也許沒有什麼變化。 並重復,直到第一次測試成功。

這樣,每個方面都經過了適當的測試,您甚至可以用一些方法重新使用。

希望這會有所幫助!