許多公司往往為了 KPI 需要數字,所以將 code coverage (測試覆蓋率) 訂了個指標來「強暴」開發團隊,甚至要求團隊「一定」要用 TDD 來開發所有程式。
這一切都是不求甚解的為了潮、為了追求數字的迷思,甚至把 code coverage 與產品品質直接劃上等號。
本篇文章將補上我對於「code coverage」與「看待 TDD 的正確角度」的見解。
100% Code Coverage ?!
在微信與 Facebook 上看到大家轉發的一篇文章:100%代码覆盖率的悲剧,讓我藉此來對 code coverage 跟 TDD 做一些補充。
先來個總綱:「一切的目標都是為了寫出好讀、好維護、好設計的產品代碼。」
有了目標我們再來看別的東西,就清楚多了。
Why TDD ?
如果你不知道怎麼簡單設計,TDD 可以幫助你,但你不一定非得要用它。
如果你不知道怎麼設計出讓呼叫端易用的 API,那 TDD 可以幫助你,但你不一定非得用它。
如果你想要讓測試案例被自動化生成文件,你應該先問一下,你產生出來的文件效益在哪,如果沒有,那你不一定需要它。
Code Coverage Criteria?
Code coverage 的數字向來不是重點,有數字時大家就只會迷思在數字,這是 KPI 思維,而錯誤的 KPI 會造成極大的浪費。
試想一下,產品程式碼的每一行重要程度都一樣嗎?有沒有可能100 行程式碼中有 90 行是在做異常判斷與處理,而只有 10 行是最核心的商業邏輯與流程?實務上正常情況,有 98% 都是跑這 10 行,只有 2% 的異常會落入其他 90 行中。
那麼,如果只追求 coverage 的絕對數字,大家就會先去寫異常處理的那 90 行,因為這好寫很多,而且輕鬆就可以讓 coverage 90%。結果最重要的核心,最常發生的情境那 10 行,卻沒被自動測試涵蓋到,這不是本末倒置嗎?
既然每一行產品程式碼的價值權重不完全相等,那 line coverage 本身的絕對數字,又能代表什麼呢?
因此,要去研究跟找到原因的應該是:「那些沒被測試涵蓋到的產品程式碼,發生什麼事了?」
是有需求存在,但漏了測試案例?它重要嗎?值得補嗎?
還是根本需求已經不存在,這只是段 legacy code, 這段產品代碼根本沒有存在的必要了。那就清掉它。
這才是看待 code coverage 的正確角度。
Code Coverage 導入團隊的 3 個步驟
- Code coverage > 0 %:針對 code coverage 若真要給個 criteria,我會建議 code coverage 至少 > 0%,也就是應該至少要有測試。
這原因是,讓後續的人只需要加測試案例即可,不需要自己建測試專案、拉參考、設定 CI config,後手的人不用從無到有,只需要新增測試程式就好,這樣就會減少很多心裡的抗拒。
- 相對趨勢 > 絕對數字:與其去訂一個 coverage > 20 %, 還不如定義,每次 build 之後,coverage 只能比原本的高,這意義是對自己這次簽入的程式碼負責(無須對前人的 legacy code 負責)。
只要這次簽入的產品程式碼都有相關的測試保護,coverage 的分母分子同時增加一樣的數字,比例只會變高,不會變低。
- 頻繁簽入:接著鼓勵大家頻繁簽入,觸發自動化的迴歸測試,享受持續整合的好處。因為 coverage 只會上升,不會下降,因此整體產品程式碼被測試保護的範圍就會越來越多,穩定的基底也會越來越多。
這其實就是 Uncle Bob 所提的童子軍法則:「讓離開時的營地比原本更乾淨。」
結論
- 測試覆蓋率的數字不是重點,辨識哪一些代碼沒被測試覆蓋到,所代表的意義才是重點。
- 相對趨勢 > 絕對數字,每個人願意為自己的部分負責(就像擦自己屁股總是甘願一點,擦別人屁股總覺得髒),測試覆蓋率只能往上提昇,不能往下掉,接著鼓勵頻繁簽入。
- TDD 是種手段,是達成目的的一種很好用、很值得投資的方式,把 TDD 當作達成目的的一種方式,而不是把 TDD 當作目標。嚴格來說,TDD 是一個好的開發習慣。
測試,對軟體開發來說,一直以來都是剛好順便、一氣呵成的輔助而已,從來都不該是目的。
【補充】上次跟曉梅老師交流了一下開發人員的測試,與測試人員的測試,其實壓根就只是同名不等義。開發人員的測試,應該稱做 CHECKING,而測試人員的測試,才稱做 TESTING。因為開發人員的測試,是針對已知的輪廓、期望進行驗證。測試人員則是探索著產品跟功能未知的部分。
參考
想要提昇 code coverage 與產品品質,想知道如何在團隊中導入與落實,請參考相關活動: