2010-05-14 47 views
4

我瞭解有關單元測試的一般概念,並將它用於系統中發生複雜交互的場景,但我仍然對所有這些原則一起提出了疑問。商業應用程序的TDD示例

我們被告誡不要測試框架或數據庫。良好的用戶界面設計不適合非人爲測試。一般的UI交互在MVC框架中被排除。在許多應用程序中剩下什麼? 37signals會談到廣泛的單元測試,但是在像Basecamp或Backpack這樣的應用程序中,通過適當的單元測試測試的事物類型究竟是什麼?在這種情況下,100%的代碼覆蓋率意味着什麼?編輯:我不拆卸應用程序,如揹包 - 他們是很棒的,但工作似乎更多地進入設計和互動,而不是複雜的邏輯(實際上,他們支持這個想法)。在那些應用程序的哪些地方,CRUD和哪個對象的層次與其相關的幾乎涵蓋了它,單元測試的適當數量爲零?這種情況下的測試點是否爲驗證代碼的另一個副本(必需的,正則表達式等)?

回答

8

業務應用程序的TDD就是這樣工作的。

  1. 寫下業務需求。

  2. 寫下該要求的測試。

  3. 編寫通過測試的代碼。

訣竅是有很多不需要大量測試的快速非業務需求。

  • 「保存到數據庫」不是業務需求。這是技術性的。

  • 「在某些情況下激活GUI上的按鈕」不是業務需求,它是接口的一部分。

  • 「備份」不是業務需求;這是安全性或業務連續性或其他。

考慮一個具體的例子。

要求 - 「在您支付罰款之前,您不能借書。」

測試。

  1. 嘗試借書與罰款。

  2. 嘗試借書沒有罰款。

代碼。

class FinesNotPaid(unittest.TestCase): 
    def setUp(self): 
     # load some fixtures with users, books and fines outstanding. 
    def test_should_not_checkout_book(self): 
     x = TheCheckoutClass() 
     x.checkoutBook(someBook) 
     self.fail("Should have thrown error") 

class FinesPaid(unittest.TestCase): 
    def setUp(self): 
     # load some fixtures with users, books and fines paid. 
    def test_should_not_checkout_book(self): 
     x = TheCheckoutClass() 
     x.checkoutBook(someBook) 
     self.success() 

class NoFines(unittest.TestCase): 
    etc. 

這些是由與您的數據庫和GUI分開的類實現的業務規則。這些是應用程序域層中的類。

您的CRUD規則業務規則。你需要測試它們。但是,您不需要測試每個與數據庫相關的功能。你需要一些「我可以創建並堅持一個對象嗎?」試驗。你必須相信ORM,數據訪問層和數據庫實際工作。您不要編寫測試來徹底測試ORM的內置功能。

代碼覆蓋率(100%或80%或10%)在很大程度上毫無意義。具有80%代碼覆蓋率測試的軟件實際上可能失敗20%?它不這樣工作。測試每一行代碼並不能覆蓋每條邏輯路徑,因此請不要擔心並開始測試。

測試業務用例。如果他們通過並且有未經測試的代碼,那麼 - 也許 - 你寫了太多的代碼。

+0

它可能會分裂毛髮,但這可能比BDD更適合TDD。這篇文章的結尾很有趣(http://consultingblogs.emc.com/jamesbroome/archive/2009/10/16/asp-net-mvc-controllers-bdd-the-perfect-match-part-3-the -accountcontroller-contd.aspx) – R0MANARMY 2010-05-14 18:11:20

+3

有些人稱之爲DDD - 域驅動開發。 BDD,DDD和TDD之間有很多不必要的分裂。我認爲他們創造了其他條款讓業務分析師感到有用。 – 2010-05-14 19:26:27

2

您正在測試以確保業務邏輯(在許多應用中,這是「服務」或「邏輯」層)與您的業務用戶對業務真實運作方式的描述相符。例如,您正在測試以確保,例如,僅僅因爲您向賓夕法尼亞州的所有購物增加了6%的銷售稅,您在給某人贈送禮品卡時也不會給您額外6%的贈金。

在UI和數據庫之間的應用程序層中有(或應該有)大量的腦汁。這是測試黑客的東西。