2010-12-08 113 views
5

我需要開發一個相當簡單的算法,但對於如何爲其編寫最好的測試感到困惑。我將如何去測試這個單元測試?

一般說明:用戶需要能夠刪除一個計劃。計劃有與其相關的任務,這些也需要被刪除(只要他們還沒有完成)。

僞代碼的算法應該如何表現:

PlanController.DeletePlan(plan) 
    => 
    PlanDbRepository.DeletePlan() 
     ForEach Task t in plan.Tasks 
      If t.Status = Status.Open Then 
      TaskDbRepository.DeleteTask(t) 
      End If 
     End ForEach 

現在據我瞭解,單元測試不應該觸碰數據庫或一般需要訪問任何外部系統,所以我猜我這裏有兩個選擇:

1)模擬出的庫調用,查看是否已經被調用的次數適當數量的斷言

2)爲兩個存儲庫類創建存根,手動設置它們的刪除標誌,然後驗證相應的對象是否已標記爲刪除。

在兩種方法中,最大的問題是:究竟我在測試的是什麼?這些測試會給我什麼額外的價值?

任何有識之士將不勝感激。這在技術上與任何特定的單元測試框架都沒有關係,儘管我們使用了RhinoMocks。但我更喜歡一個一般的解釋,以便我可以適當地包裹我的頭。

回答

4

您應該模擬知識庫,然後在包含打開和關閉任務的單元測試中構建一個虛擬計劃。然後調用通過此計劃的實際方法,並最終驗證DeleteTask方法是否使用正確的參數調用(只有status = Open的任務)。通過這種方式,您可以確保只有與此計劃關聯的打開任務已被您的方法刪除。另外不要忘記(可能在一個單獨的單元測試中)通過聲明已在您傳遞的對象上調用DeletePlan方法來驗證計劃本身已被刪除。

2

要添加到Darin的答案我想告訴你你正在測試什麼。這裏有一些業務邏輯,例如檢查狀態。

此單元測試現在看起來可能有點愚蠢,但未來對代碼和模型的更改會如何?這個測試對於確保這個看似簡單的功能始終保持正常工作是必要的。

2

如您所述,您正在測試算法中的邏輯表現如預期。你的方法是正確的,但是考慮未來 - 幾個月後,這個算法可能需要改變,不同的開發人員將其切換並重新使用,從而漏掉了一個關鍵的邏輯。您的單元測試現在會失敗,開發人員會收到錯誤提醒。單元測試在開始時以及周/月/年時都很有用。

如果您想添加更多,請考慮如何處理故障。讓你的數據庫模擬器在刪除命令上拋出一個異常,測試你的算法是否正確處理了這個問題。

2

由你的測試所提供的額外價值是檢查你的代碼做正確的事情(在這種情況下,刪除該計劃,刪除與該計劃相關聯的所有打開的任務,並留下與計劃相關的任何封閉的任務)。

假設您已經爲您的存儲庫類進行了測試(即他們在對其調用刪除時做了正確的事情),那麼您只需檢查是否適當地調用了刪除方法。

你可以編寫的一些測試如下:
刪除一個空的計劃只需要撥打DeletePlan
刪除具有兩個未完成任務的計劃是否對這兩個任務調用DeleteTask
是否刪除具有兩個已關閉任務的計劃完全不會調用DeleteTask
刪除一個打開和一個關閉的任務調用DeleteTask一次正確的任務計劃?

編輯:我會用Darin的答案,去了解它,雖然道路。

0

我不會寫單元測試,是因爲對我來說這不是測試行爲,而是執行。如果在某些時候您希望偶然行爲不會刪除任務,而是將其設置爲「禁用」或「忽略」狀態,則您的單元測試將失敗。如果以這種方式測試所有控制器,則單元測試非常脆弱,需要經常更改。

重構出業務邏輯的「TaskRemovalStrategy」如果你要測試的業務邏輯,這和離開去除的實施細則到類本身。

0

IMO你可以編寫單元測試抽象PlanRepository各地和相同的測試應該在數據庫也在測試數據的完整性非常有用。

例如,你可以寫一個測試 -

void DeletePlanTest() 
{ 
    PlanRepository repo = new PlanDbRepository("connection string"); 
    repo.CreateNewPlan(); // create plan and populate with tasks 
    AssertIsTrue(repo.Plan.OpenTasks.Count == 2); // check tasks are in open state 
    repo.DeletePlan(); 
    AssertIsTrue(repo.Plan.OpenTasks.Count == 0); 
} 

即使你的資料庫中刪除的計劃,你的數據庫通過級聯刪除觸發器刪除相關任務這個測試工作。

這種測試的價值在於測試運行的是PlanDbRepository還是MockRepository它仍會檢查行爲是否正確。因此,當您更改任何存儲庫代碼甚至數據庫架構時,都可以運行測試來檢查沒有任何問題。

您可以創建這樣的測試覆蓋你的資料庫中所有可能的行爲,然後使用它們,以確保您的任何更改不會破壞實現。

您也可以參數化這個測試用一個具體的實例庫和重用他們檢測的所有未來版本庫的實現。

1

有趣的是,我發現單元測試有助於將注意力集中在規範上。 爲此讓我問這個問題......

如果我有3個任務計劃:

Plan1 { 
Task1: completed 
Task2: todo 
Task3: todo 
} 

,我呼籲刪除他們,如果發生什麼計劃?

Plan1 : ? 
Task1: not deleted 
Task2: deleted 
Task3: deleted 

是否將plan1刪除,孤兒task1?或者它是否被標記刪除?

這是i的值在單元測試中看到(雖然這僅僅是4個值的1: 1)的一個大的部分規格 2)反饋 3)迴歸 4)粒度

至於如何測試,我不會建議嘲笑。我會考慮2部分方法 第一個看起來像

public void DeletePlan(Plan p) 
{ 
    var objectsToDelete = GetDeletedPlanObjects(p); 
    DeleteObjects(objectsToDelete); 
} 

而且我也不會測試此方法。 我會測試GetDeletedPlanObjects方法,它無論如何都不會觸及數據庫,並且會允許您發送上述情況......然後我會用www.approvaltests.com聲明,但這是另一個故事: - )

快樂測試, Llewellyn

相關問題