編寫單元測試的用例是驗證代碼的正确性,很多情況下,我們傾向于讓測試沿着主路徑,也就是”happy path"前進,僅能驗證代碼的功能,卻無法保證代碼的健壯,是以本文就将解決單元測試測試什麼這個問題。
在《Pragmatic Unit Testing in Java 8 with JUNIT》這本書中,采用了RIGHT-BICEP(一種訓練二頭肌的器械)這個助記符來幫助記憶編寫單元測試的要點。
Right Are the result right?
B Are all the boundary conditions correct? 邊界條件都正确嗎?
I Can you check inverse relationships? 是否檢查反向關系?
C Can you cross-check results using other means? 是否進行了交叉檢查?
E Can you force error conditions to happen? 是否檢查了異常情況?
ßP Are performance characteristics within bounds? 性能是否在設計範圍内?
[Right]-BICEP 結果都是正确的嗎
- 測試最重要的目的是确認代碼産生了預期的結果
- RIGHT這個詞首先反應了單元測試最重要的點,也即“正确性”
- TDD是一種好的實踐方式,它要求我們首先在了解業務的基礎上編寫單元測試
- 有些時候需求未确定,但測試仍然可以進行,變更不可避免,要學着去适應
Right-[B]ICEP:Boundary Conditions 邊界條件
編寫單元測試用例時需要考慮邊界條件,如:
- 不合常理的名稱,如"!*W:X\&Gi/w$→>$g/h#WQ@
- 格式不正确的資料,如缺少了頂級域名的郵箱位址:fred@foobar
- 可能導緻溢出邊界條件
- 空值,null值或者0值
- 超出合理範圍的輸入條件,如150歲的人
- 在本不應重複的記錄中出現了重複的記錄
- 應該排序的輸入未排序
- 本應該按照時間順序發生的未按照時間順序發生
另外需要注意:以上是常見的邊界條件,在編寫單元測試用例時可以參考。需要注意的一點是,單元測試到什麼程度是由編寫者來決定的,例如團隊内的單元測試與向外暴露的單元測試的覆寫可能不同,對外提供的接口,由于輸入參數不可信程度更高,是以需要更加全面的測試覆寫。
邊界條件助記符 CORRECT
- Conformance 一緻性,輸入與期待的格式一緻嗎?
- Ordering 一組輸排序和不排序有影響嗎?
- Range 輸入是否在合理的範圍内?
- Reference 代碼是否依賴了任何外部資源,而這外部資源不受控?
- Existence 輸入存在嗎?非空,非零...
- Cardinality 基數,是否提供了足夠的輸入
- Time (絕對和相對的)事情都是按照順序發生的嗎?是否在合适的時間,以及及時發生?
Right-B[I]CEP: Checking Inverse Relationships 檢查反向關系
從反向關系驗證意味着找尋一條與現有邏輯不通的方案進行驗證,如驗證插入語句時通過查詢語句驗證。
Right-BI[C]EP:Cross-Checking Using Other Means 交叉檢驗
可以通過針對目标的不同實作方式來進行檢驗,這種檢驗被稱為交叉檢驗,如不同的算法。
Right-BIC[E]P: Forcing Error Conditions 引發錯誤的條件
好的單元測試不是那種簡單的覆寫明顯的邏輯路徑的,而是要詳盡考慮不同的異常情況,對代碼的邏輯提供有效保護。
異常情況也是單元測試需要考慮的内容,下面是常見的一些需要考慮的狀況。
- 記憶體不夠
- 磁盤空間不夠
- 挂鐘時間問題
- 網絡可用性以及錯誤
- 系統負載
- 受限的調色闆?
- 非常高或者非常低的視訊清晰度
Right-BICE[P]: Performance Characteristics 性能特性
過早優化是萬惡之源的出處:
Rob Pike of Google: “Bottlenecks occur in surprising places, so don’t try to second guess and put in a speed hack until you have proven that’s where the bottleneck is.”
- 可以通過設計單元測試幫助查找性能問題所在
- 對于測試性能的單元測試,因測試的執行時間依賴于環境,是以除了在同一環境運作外,沒有太大的比較意義
- 更常用的場景是提供了一個優化基線,通過單元測試能夠不斷看出優化效果(實際就是一段驅動代碼)
- 如果性能是産品的關鍵考量,應該從更高層次考慮(JMETER),而非采用單元測試
- JUnitPerf可以提供單元測試級别的性能測試能力