2009-11-02 60 views
4

當我的方法從一開始看起來不正確時,我必須開始使用QualityTools.UnitTestFramework爲我們開發的Web服務層編寫一些單元測試。單元測試複雜交互的正確方法

似乎單元測試應該能夠以任何順序運行,而不依賴於其他測試。

我最初的想法是有類似於以下測試(簡化expample)的東西,它將以相同順序作爲有序測試運行。

AddObject1SuccessTest
AddObject2WithSameUniqueCodeTest
(依賴於擁有創建object1第一測試第一然後期望失敗)
AddObject2SuccessTest
UpdateObject2WithSameUniqueCodeTest
(依賴於第一測試已經創建object1並且具有創建THRID測試object2先預計失敗)
UpdateObject2SuccessTest
GetObjectListTest
DeleteObjectsTest
(使用添加的ID)

然而,測試和說添加的ID到deletetest例如傳球的沒有明顯的方法之間不存在狀態。

那麼,單元測試複雜交互的正確方法是否是由場景決定的?

例如

AddObjectSuccessTest
(其創建一個對象,獲取它來驗證的數據,然後將其刪除)
AddObjectWithSameUniqueCodeTest
(它創建的對象1,則嘗試創建對象2然後刪除對象1)
UpdateObjectWithSameUniqueCodeTest
(它創建對象1然後創建對象2,然後嘗試更新對象2,使其具有與對象1相同的唯一代碼,然後刪除對象1和對象2)

我是否出現了這種錯誤?

由於

回答

5

它是每個測試用例應該獨立於任何其他測試情況的​​單元測試的宗旨。 MSTest(以及所有其他單元測試框架)通過不保證測試運行的順序來執行此操作 - 有些(xUnit.NET)甚至可以在每次測試運行之間隨機化命令。

這也是一個推薦的最佳做法,單位凝結成簡單的互動。雖然不能提供硬性規則和快速規則,但如果交互過於複雜,則不是單元測試。無論如何,複雜的測試是脆弱的,並且維護費用非常高,這就是爲什麼簡單的測試是首選。

這聽起來像你有你的測試之間的共享狀態的情況。這導致相互依賴的測試,應該避免。相反,您可以編寫可重複使用的代碼,爲每個測試設置前提條件狀態,確保此狀態始終正確。

這種預調節狀態稱爲夾具。本書xUnit Test Patterns包含許多關於如何在許多不同場景下管理夾具的信息和指導。

+0

有時建立先決條件狀態可能會很昂貴。你對如何處理這種情況有任何想法嗎? – 2009-11-03 19:42:50

+0

如果可能的話,所謂的不可變共享夾具是最好的方法。同時,很多併發最佳實踐也適用於管理測試夾具:如果可能,不要共享狀態。如果你必須共享狀態,它是最簡單的,如果它是隻讀的等等。不可變的共享夾具是一個永遠不會改變的夾具。然後,您可以在不可變共享夾具上建立一次性夾具,確保這些夾具在每個測試案例之後被拆除。通常它是最昂貴的Fixture的不可變部分(例如,建立一個DB),所以這種模式運行良好。 – 2009-11-03 20:31:49

3

爲補充什麼馬克說,是的,每個測試應該從別人完全獨立的,並使用你的條件,每個測試應該是一個獨立的情況下,它可以獨立於其他的運行。
我從假設你的描述,你正在測試的持久性,因爲你在步驟有你在測試結束時創建實體的缺失,清理狀態。理想情況下,單元測試完全在內存中運行,每次測試之間沒有共享狀態。一種方法是使用Mocks。我假設你有一個類似於Repository的東西,以便你的類調用Repository.Add(myNewObject),它調用類似Repository.ValidateObjectCanBeAdded(myNewObject)的東西。不是針對真正的存儲庫進行測試,它會在數據庫中添加對象,並且需要刪除它們以在測試之後清除狀態,您可以使用兩種相同的方法創建一個接口IRepository,並使用模擬來檢查當您的類調用IRepository,它以正確的順序用正確的參數行使正確的方法。它還使您能夠在內存中將「假」存儲庫設置爲任何您想要的狀態,而無需物理添加或刪除實際存儲中的記錄。
希望這有助於!

+0

@Mathias,Mocks似乎是一種測試業務邏輯的好方法 - 它並不關心它正在處理的存儲庫。但是,你如何測試你的實際數據訪問?如果我使用mock,那麼我如何測試數據庫更改,存儲過程或查詢更改以及數據訪問代碼?在我看來,在許多LOB應用程序中,數據訪問是應用程序中一個重要且相當大的部分。 – 2009-11-03 14:21:30

+0

@Mathias,感謝您的信息,但這聽起來像是構建了很多測試基礎架構,它們只是以不使用現有數據層的方式複製現有數據層,這意味着更多需要維護的代碼隨着事物的變化而變化,當我只想測試應用程序是否按照預期的要求執行,並建議當應用程序本身無法正常工作時,模擬存儲庫的測試可以通過? – 2009-11-03 15:23:49

+0

@Tuzo和Adam:我可能已經更清楚了,我的道歉。在你係統的某個地方,一個班負責堅持,並且應該進行測試。但是,這通常被認爲是集成測試,而不是單元測試。這是昂貴的(複雜的設置和長時間運行),這就是爲什麼mock可以提供幫助:你可以更頻繁地運行昂貴的測試,但是有單元測試可以快速檢查系統是否正常工作,如果「昂貴」正確的合同。 – Mathias 2009-11-04 01:45:46