什麼是單元測試

在寫laravel的測試時
5.4版本之後你會看到/test底下會有Unit/Feature/ 後來我才知道這兩個的區別:
單元測試(Unit) : 測試一個單純功能的完整性,例如測試你自訂的數字相加function,細看的話有判斷傳入值是否為數字、判斷結果是否為數字這兩個測試項目
功能測試(Feature) : 測試一個系統功能的完整性,例如測試產生訂單功能,裡面包含了驗證傳入資料、產生訂單資料…

單元測試 : 應為工程師寫,使用TDD開發流程 => 不具備邏輯
功能測試 : 應為測試工程師寫,避免工程師寫的時後所產生的流程盲點 => 具備邏輯

單元測試,簡單的說,就是用來模擬外部如何使用這個目標物件,或是如何與這個目標物件互動。
所以我們所撰寫的單元測試程式,就是模擬與目標物件互動的程式。
測試案例,就是該互動下的情境。接著驗證物件的行為是否符合我們預期。

  • 一個測試案例只測一種方法
  • 最小的測試單位
  • 不與外部(包括檔案、資料庫、網路、服務、物件、類別)直接相依
  • 不具備邏輯
  • 測試案例之間相依性為零

當出現非預期的執行結果時,通常代表目標物件有著非預期的行為發生,有可能是當初測試案例不足,所以要增加我們的「預期」。

大家肯定也寫過一堆「系統分析書」、「程式規格書」、「SA/SD文件」等等…但這些文件,跟最後線上的程式碼,究竟有多少是相同的呢?文件越詳細,代表後面修改的effort越大。

軟體設計,本來就是個需求頻繁變動的過程,往往大家只想「凍結需求」,卻很常因為「凍結需求」搞到作出來的系統難用,因為不符合使用者需求。(我們期望的是,每一次的需求異動,都是軟體進化的動力,每一次的異動,都是品質的累積,以及更符合使用者的需求。)

前期準備

  • 了解 TDD/BDD 是什麼
  • 了解 phpunit 所產生的 coverage-html 內容,並找出測試不足的地方
  • 了解有哪些測試斷言 : phpunit assertions
  • 了解如何使用 Mock (重要)
  • Facade也有Mock,ex : Cache, Session, Vi => 如何使用,該用在哪
  • 了解 factory 如何製造測試假資料

實作要點

這邊稍作記錄一些重點,之後會再寫實作測試的章節

  • use RefreshDatabase; : TestCase中使用這個trait後, 每次測試run完假資料後, 會自動reset database
  • setUp() : 測試class 起始時會執行的function => 像 __construct()
  • tearDown() : 測試class 結束時會執行的function
  • mock次數function : once(), twice(), times(int)
  • mock指定傳入參數function : with(string)
  • mock允許傳入任何參數function : withAnyArgs()

結論

本篇是介紹我TDD實作完後的一些心得感想
其實這個範例才剛開始沒多久
沒有多少可怕複雜的系統功能
所以趁現在好好把一些架構底子打好
但是在實作測試後
才發現測試是一門高尚的學問
其實我相信很多人都知道要單元測試
但大多數人會因為案子太趕直接丟到測試環境測就好有點複雜不習慣…等相關理由
而忽略單元測試這環
雖然我才剛入門了解沒多久(一週) 但如果真的有好好做好單元測試
後面可以省下維護的成本是很可觀的
最實際的案例就是

1
2
3
系統做完了,有一些專案文件,上線沒多久後相關人員離職了  
接下來新人進來,不知道該從何下手  
更可怕的事,有些莫名的功能專案文件上還沒有提到  

如果有寫測試的話
新人可以follow測試的腳本確認功能流程
每個測試單元也能掌握該如何維護修改

開發系統若加了測試流程
雖然會增加功能開發時程
但是可以確保每個上限的功能品質
就看公司願不願意投資這個流程摟

Reference