Clean code (2) 再談 Unit test



Clean code 裡頭我想談的第二個讓我豁然開朗的地方就是他談單元測試。到底該不該做單元測試,我想目前已經沒有疑義了,但是究竟單元測試該測到什麼地步呢? 我們直接看 Bob 大叔在書內程式碼的的氣味和啟發一章所提關於測試的九點:

  1. 不足夠的測試 - 一套測試組應該包含多少個測試呢? 不幸的是,許多程式設計師所使用的標準是 "這看起來似乎是夠多了"。一套測試組應該測試所有可能失敗的情況。只要有任何的條件沒有被測試過,或任何的計算沒有被驗證過,那麼這套程式組就還是不足夠的。我的媽啊! 這真的是嚴苛的標準啊,看起來寫程式與寫單元測試的時間真的應該是 1:1 甚至是 1:2 才對。
  2. 使用涵蓋率工具 - 涵蓋律工具告訴你,你的測試策略裡有哪些地方並未測試到。他們也讓你容易找到尚未測試構的模組、類別和函式。大部份的 IDE 會提供你視覺上的指示,將已經被測試涵蓋到的程式碼標成綠色的,然後將為涵蓋到的程式碼標是為紅色的。這樣子可以更快速和容易找到那些還沒有被測試道的 if 或 catch 敘述。基本上,這還是再強調覆蓋率必須百分之百啊!
  3. 不要跳過簡單的測試 - 這些簡單的策是很容易撰寫,而且這些測試文件的的說明價值高於撰寫的成本。好了,一個壞消息一個好消息。壞消息是,還是得有百分百的涵蓋率,好消息是,寫測試有其他的意義。那是不寫測試得花更多成本達成地。
  4. 被忽略的測試是對模稜兩可的疑問 - 有時候因為程式的需求不夠明確,所以我們無法確定某個行為的細節。我們可以利用被註解掉的測試,或者被標記成 @Ignore 的測試來表達我們對於需求的疑問。至於你該選擇哪種做法,取決於模稜兩可的部分是否想要被編譯。嗯,作者幫我們找了第二個測試可以提供的用途,感覺比較好一點了。
  5. 測試邊界條件 - 特別注意測試邊界條件,我們會遇到,演算法在一般狀況下運行順利,但在邊界條件時卻判斷錯誤。好,這是一個很好的線索,這可能是所有測試中,除了功能要符合預期的測試外,最重要的測試項,所以可以把這類測試擺在比較前面實作。吚? 我有說如果時間不夠,其他的來不及就算了嗎? 是你聽錯了吧!
  6. 在程式錯誤附近進行詳盡的測試 - 程式錯誤往往聚集。當你再函式裡找到否個程式錯誤,明智的做法是對該函式做一個詳盡的測試。你可能會發現程式錯誤其實並不只有一個。這個明顯是再談如果你用到一段沒有單元測試的原始碼的狀況,或者你的系統原來沒有單元測試,後來被 QA 找出問題後的處理方式。所以新寫的程式碼,還是應該按照前面的幾個原則寫單元測試。
  7. 失敗的模式是某種啟示 - 有時候你可以利用測試程式失敗的模式,來診斷程式的問題在哪裡。這是另一個要使得測試盡可能完整的論點,完整的測試以合理的方式排序時,就能透露出失敗的模式。這段中文的意思看不是很懂,不過我看得懂他說了,"測試盡可能完整"。
  8. 測試涵蓋率模式可以是一種啟示 - 查看在測試時執行過或未被執行的程式碼,就能對失敗的測試為什麼失敗,提供一些蛛絲馬跡。說了半天,就是說沒有測試過的程式碼,會隱藏出錯的機會,所以涵蓋率要夠廣。
  9. 測試要夠快速 - 一個龜速的測試是個不會被執行的測試。當行程很趕時,龜速的測試會從測試組裡被移除。所以盡力保持你的測試程式夠快速。這點跟涵蓋率比較不相關,但是提醒我們單元測試的使用情境,一定要保持他快速執行的特點。
所以通過這九點觀察,我們可以得出一個結論,請追求盡可能的單元測試涵蓋率。所以導入單元測試對於過去沒有寫測試的人來說,就是一個雙倍時間的投資。不過我相信他絕對是值得的。

0 comments