天天看點

三、單元測試要測試的是什麼? The Right-BICP

編寫單元測試的用例是驗證代碼的正确性,很多情況下,我們傾向于讓測試沿着主路徑,也就是”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可以提供單元測試級别的性能測試能力