Skip to content

單元測試的藝術

單元測試基礎

:::warning 單元測試的價值? 開發人員提升程式品質, 加深理解類別或方法功能需求的最佳方式之一

注意維護成本和時間 :::

工作單元 最終結果

整合測試

單元測試框架

知道如何區分單元測試和整合測試

第一個單元測試

在真實世界中, 你應該測試任何包含邏輯程式碼的方法, 不管它看起來有多簡單 邏輯可能有時會失敗, 而且你想知道何時會失敗, 失敗是甚麼原因所導致

==測試命名==和位置的基本規則

  • UnitOfWorkName
    • 被測試的方法
    • 一組方法
    • 一組類別
  • Scenario
    • 測試進行的假設條件
      • 舉例: 登入失敗, 無效的使用者, 密碼正確, 系統記憶體不足, 無此使用者, 該使用者已經存在
  • ExpectedBehavior
    • 在測試情境指定的條件下, 對==被測試方法行為==的預期
      • 回傳一個結果值(真實的值或是例外)
      • 系統狀態的改變
        • 舉例: 在系統中新增了一個使用者, 導致在下一次登入時系統的行為發生變化
      • 呼叫了外部第三方系統所提供的服務
        • 舉例: 和一個外部的Web服務進行互動

一個單元測試通常包含了三個行為

  • 準備(Arrange)物件, 建立物件, 進行必要的設定
  • 操作(Act)物件
  • 驗證(Assert)某件事符合預期

使用參數來重構測試

LogAnalyzer analyzer = new LogAnalyzer();
...

假設現在已經寫了三個測試, 裡面都包含了上面的準備物件程式碼 若在類別LogAnalyzer的建構式加入一個參數, 那麼三個測試都會編譯失敗 若真實環境中不是三個而是30或300個呢?

參數化測試(parameterized tests)

單元測試的生命週期注意事項

進行單元測試時, 很重要的一點是確保之前測試過程中所遺留下來的資料或執行個體得以銷毀 新的測試執行時, 狀態是重置過的

setup和teardown 必須注意的是使用setup越多, 測試程式的可讀性就越差 :::warning 為了理解測試是怎麼得到物件執行個體, 使用的物件是甚麼型別, 人們不得不同時去看檔案裏面的兩處程式 :::

本書作者並不使用setup來初始化被測試類別的物件執行個體, 而是採用==工廠方法==(factory method)來初始化被測試的物件執行個體

在單元測試的專案中, 幾乎永遠不會用到TearDown或TestFixture方法 只有一種情況下在單元測試中使用TearDown是有意義的, 亦即需要在測試和測試之間重設一個靜態變數或單例(Singleton)的狀態 任何其他的情況下使用TearDown, 都可能是在進行整合測試

測試系統狀態的改變而非驗證回傳值

驗證被測試系統在執行某個動作的前後,其行為所發生的變化是否符合預期

透過虛設常式解決依賴問題

使用模擬物件驗證互動