我討厭單元測試:滕振宇談如何進行單元測試

(本文首發於InfoQ中文站:http://www.infoq.com/cn/news/2012/02/I-Hate-Unit-Test

說起單元測試的好處相信大家都能列舉出不少,可是很多時候,開發人員面對自己產品的代碼,想寫單元測試卻無從下手,久而久之,便會有人大喊:“我討厭單元測試。”資深敏捷諮詢師騰振宇(Daniel Teng)在GTUG-TopGeek開發工程管理沙龍就以此爲題,結合最近的一個項目,和大家分享了他對單元測試的一些看法。

Daniel先介紹了下最近的一個項目,雖然不是遺留系統,但代碼已經慘不忍睹,而且缺乏必要的測試保障,要修改代碼可謂舉步維艱。例如,一段代碼和結對夥伴讀了半小時沒讀懂,找來原作者看着註釋又想了10分鐘,終於才搞明白這段代碼是做什麼的。根據二八原則,先找到那20%的點,修改它帶來80%的價值。最直接的做法就是尋找代碼庫裏最常被修改的文件,一般的文件只有幾次修改,有的文件則被修改了幾十次,每個人都在往復雜的代碼里加入新的東西,但沒有人往裏面加測試,於是第一步就是爲它增加測試。

很多開發者會說老項目就算了,如果新啓動一個項目,我就會寫單元測試了,Daniel認爲這是一個“美好的夢想”,很多原因會打破它:

  • 代碼已經很爛了,又沒辦法下手了
  • UI不好測
  • 認爲這是QA的工作
  • 寫的單元測試找不到Bug
  • 代碼的外部依賴太多
  • 代碼稍作修改,測試也要一併修改,太麻煩了

究其根本原因,是開發者根本不會寫單元測試!滿足什麼標準的測試纔是單元測試呢?根據《修改代碼的藝術》,需要訪問數據庫的測試不是單元測試,需要訪問網絡的測試不是單元測試,需要訪問文件系統的測試不是單元測試……

爲了更方便地進行單元測試,業務代碼應避免以下情況:

  • 存在太多條件邏輯
  • 構造函數中做的事情太多
  • 存在太多全局狀態
  • 混雜了太多無關的邏輯
  • 存在太多靜態方法
  • 存在過多外部依賴

例如,在代碼中存在硬編碼,或者是直接創建了一個數據庫連接,這種做法都是比較危險的,因爲在測試時沒有辦法“偷樑換柱”。

想要寫好單元測試,學會重構是很重要的,重構的過程類似於清理廚房,雖然和做飯沒太大關係,但可以讓您下次做飯更方便,心情更好。可以重構的地方包括,在待測試類與其依賴之間增加一層Test Fixture;將創建邏輯與業務邏輯分開等等。重構可以採取以下策略:

  • 編寫測試代碼建立基本的防護網。在單元測試和功能測試之間要有取捨,如果單元測試實施成本很高,可以先加功能測試。
  • 通過增加中間層來打破依賴,不是爲了去掉依賴,而是爲了後續的修改以及測試的便利。
  • 將第一步中編寫的功能測試換成單元測試。

最後,Daniel還爲大家提了一些建議:

  • 項目裏的破窗要修好,別容忍別人加新的破窗,用測試將破窗保護起來。
  • 當你離開一個地方的時候,要讓它比你來的時候更整潔乾淨。(童子軍軍規)
  • 不停地重構你的代碼,每次走一小步。

隨後有人提問,如何評估一個單元測試的質量,用代碼行覆蓋率是否可行。Daniel認爲沒必要去追求代碼行覆蓋率,真正要覆蓋的是邏輯,而不是代碼行。通過結對編程可以減少低質量的單元測試,人都喜歡改變,但沒人喜歡被改變,不要強求結對編程,讓他看到好處,嚐到甜頭,吸引他來做結對編程,沒有人喜歡落後,比如50%的人在做結對了,剩下的人自然會想嘗試。

當被問及單元測試是否是必須的時候,Daniel回答這並不是必要的,而是需要進行綜合的衡量,比如你的競爭對手一週前推出了一個產品,你需要在一週內完成產品研發並上線,這時可以選擇寫或者不寫單元測試,對於沒有寫過單元測試的人,一開始是需要上手的成本的。

如果您也對單元測試的話題感興趣,不妨關注騰振宇的博客微博,也可以觀看會議視頻


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章