2011-07-05 110 views
0

的具體測試及流量我很新。我正在用phpUnit進行開發,但是由於我的問題是更一般/設計問題,所以實際環境不應太重要。單元測試:在一般的單元測試和測試控制

我認爲,儘可能詳細地編寫您的測試用例是一個好習慣。例如(越晚越好):

assertNotEmpty($myObject);    // myObject is not Null 
assertInternalType('array', $myObject); // myObject is an array 
assertGreaterThan(0, count($myObject)); // myObject actually has entries 

如果這是正確的,這裏是我的問題

它是一個公認的做法,以編寫測試用例內一些流量控制,如果測試對象的狀態取決於外部來源(即數據庫) - 甚至一般?

像:

if (myObject !== null) { 
    if (count(myObject) > 0) { 
    // assert some Business Logic 
    } 
    else { 
    // assert some different Business Logic 
    } 
} 

就是這種流量控制的測試用例內受理或者是一個「代碼味道」,應該回避?如果沒問題,是否有任何提示或做法,這裏應該記住?

回答

3

Paul的回答解決了測試方法範圍和斷言問題,但您的問題代碼隱含的一件事是,如果返回的對象具有值X,則測試A,但如果測試值B具有值Y,則測試B.換句話說,您的測試期望多個值並根據實際得到的結果測試不同的事物。

一般情況下,你會更快樂的測試,如果你的每個測試有一個單一的,已知的,正確的值。您可以通過使用固定的已知測試數據實現此目的,通常通過將其設置在測試本身內部來實現。以下是三條常用路徑:

  • 用一組所有測試使用的固定數據填充數據庫。隨着您添加更多測試和功能,這將會發展,隨着事情的發展,保持最新狀態會變得很麻煩。如果您有測試修改數據,則需要在每次測試後重置數據或回滾更改。
  • 創建一個精簡的數據爲每個測試設置。在setUp()期間,測試將使用其特定數據集刪除並重新創建數據庫。它最初可以使寫作測試更容易,但是您仍然必須隨着對象的發展更新數據集。這也會使運行測試需要更長的時間。
  • 使用嘲笑爲數據訪問對象時,沒有直接測試這些DAO的。這允許您在測試中指定應該返回哪些數據以及何時返回。由於您沒有測試DAO代碼,因此可以將其嘲笑出來。這使得測試可以快速運行,並且意味着您不需要管理數據集。然而,你仍然需要管理模擬數據,並編寫模擬代碼。根據您的喜好,有許多模擬框架,包括PHPUnit自帶的嵌入框架。
+2

Definitly!該示例顯示了至少三個測試用例(有時似乎myObject可以並且應該爲空,有時它有一個計數,有時它不會),並且每個測試應該是一個測試用例,並像@David顯示的那樣創建。如果你繼續像這樣一個@SunnyRed建設測試,我會說你會遇到很大的麻煩,只是因爲你的測試套件不會顯示你測試過的許多事情的錯誤。 +1 @David – edorian

+1

感謝您對David的貢獻。我將它標記爲正確的答案,因爲你更精確地覆蓋了我原來的關注點。 你說得很對,我不知道,我的結果反映了當前狀態,因此需要區分。 關於「解決途徑」:他們中的一個是最佳實踐還是以任何方式最常見的途徑,還是僅僅是一種風格問題? – SunnyRed

2

沒關係讓你的測試用例中的某些控制流,但在一般情況下,瞭解你的單元測試將制定出最好的,如果他們不相交,也就是說,它們每次測試不同的事情。這工作進行的順利的原因是,當你的測試用例失敗了,你可以精確瞭解失敗是失敗,而不是需要去更深更大的測試案例裏面看到了什麼錯誤的測試用例什麼。通常的度量是每個單元測試用例的單個斷言。也就是說,每條規則都有例外,這當然是其中之一;在測試用例中有幾個斷言沒有什麼不妥,特別是當測試用例場景的設置/拆卸特別困難時。然而,你想避免的真實代碼氣味是你有一個測試所有代碼路徑的「測試」的情況。

+0

謝謝保羅。你的回答接近我的想法。現在我知道了,並且學到了一些新東西。謝謝! – SunnyRed