軟件開發過程當中值不值得寫單元測試?

原文連接: https://voidint.github.io/pos...git

1、不寫單元測試的理由

工做幾年,遇到過很多抗拒寫單元測試的人,總結一下大體有如下這麼幾個理由:github

首先,寫單元測試所支出的時間可能比實現功能自己所花費的時間還多。言外之意,在實現完全部功能以前不值得寫單元測試。若是現階段功能開發大體完畢,可能也不會去補上虧欠的單元測試,理由大體有這麼幾點:框架

  • 需求老是無窮盡的,還有下階段功能需求要實現,沒空補單元測試。
  • 要補的單元測試太多,無從下手,主觀上抗拒。
  • 單元測試編寫難度大。一方面緣由多是功能函數實現上不夠合理,另外一方面是沒有(或者不知道)好用的單元測試框架和mock框架。
  • 單元測試不算入工做量內。

其次,功能需求還不穩定,寫單元測試的性價比不高。換句話說,萬一明天需求一變,那不光功能代碼廢了,單元測試也廢了。若是不寫單元測試,那這部分工夫就不會白費。函數

2、寫單元測試的投入產出比

投入產出比做爲這個問題的判斷依據,我以爲是全部理性人都會作出的選擇。而既然引入了投入產出比這個經濟學上的概念,那麼應該也能接受另外一個經濟學上的普世規律——邊際收益遞減。以及資源(主要指時間和精力)具備稀缺性這一規律。post

下面的分析都將是創建在以上這些共識的基礎之上,若是你並不認同這些規律一樣能夠用來分析軟件開發過程當中值不值得寫單元測試這個問題,那麼閱讀如下內容僅僅是在浪費你寶貴的時間。若是你繼續往下閱讀,那麼,我將假設你已經和我達成了這些共識。單元測試

雖然要爲這個問題作精確的投入產出比定量分析比較困難,但並不妨礙咱們經過定性分析來得出本身心中的答案。測試

成本(投入)

  • 編寫單元測試用例所額外付出的時間,短時間內會拖慢項目進度。

收益(產出)

  • 提高代碼質量。監督開發人員寫出更加易於測試和可維護的代碼。
  • 提高開發團隊內部的協做效率。其餘開發人員能夠經過閱讀單元測試用例來理解代碼原做者的意圖。
  • 保證功能實現的長期穩定。代碼一旦發生與原功能意圖不相符的變化,經過跑單元測試能夠體現出來,便可以防止功能被無心識地破壞。
  • 提升自動化測試佔比,下降其餘測試方式上的投入。

從上面我所羅列的成本/收益數量上說,收益的數量遠大於成本。可是,分析投入產出比並非掰手指數數量就能得出答案的,特此說明。code

首先,短時間項目不寫單元測試是划算的選擇。至於到底多長時間算做短時間,並沒有定論。我選擇將一個月做爲劃分的界限,一月之內爲短時間,多於一月是中期或者長期,至於中長期的界限在哪兒,這個可有可無,暫且不論。生命週期

短時間項目的典型表明就是演示用demo項目。這類項目的共性是時間緊迫,項目生命週期短,無需後續的維護,使用一次性(或者接近一次性)。若是說中長期項目的使用週期(區別於開發週期)是時間段的話,那麼短時間項目的使用週期就是一個時間點或者幾個時間點。這種狀況下將有限的資源投入到單元測試中,所得到的收益並不明顯。若是繼續追加投入,因爲收益增幅平緩,投入產出比極低,甚至爲負。索性零投入零產出,雖然略顯保守,但也不失爲一個好的選擇。資源

其次,中長期項目不寫單元測試絕對不是划算的選擇。請注意,這裏我並無說中長期項目寫單元測試是划算的選擇這樣的話。由於寫單元測試這個說法太寬泛。很明顯,單元測試覆蓋率1%99%是有巨大區別的,而這二者都屬於寫單元測試這個範疇。

對於中長期項目,將資源投入到單元測試上所得到的收益曲線會是這樣(不太會畫圖,暫且用文字描述):

  • 橫座標爲投入,縱座標爲產出。
  • 開始階段,隨着投入的增長,收益(產出)增幅明顯,曲線比較陡峭。
  • 當投入到達某一臨界值,單位投入所得到的收益最大。
  • 當投入繼續追加並超過臨界值,收益的增幅明顯放緩,曲線開始變得平緩,單位投入所得到的收益愈來愈少,即邊際收益遞減。

若是你也承認以上的投入產出比曲線,那麼不難推出如下幾個結論:

  • 不寫單元測試必定不是最佳選擇。不寫單元測試能夠理解爲是零投入/零成本,那麼必然的也會是零收益。
  • 寫單元測試而且單元測試的覆蓋率接近100%也必定不是最佳選擇。因爲邊際收益遞減,投入一旦越過臨界值,那麼繼續追加投入所帶來的收益將愈來愈少。
  • 臨界值纔是理論上的最佳選擇。

上面提到的臨界值是屬於寫單元測試的範疇,而且單元測試覆蓋率在0%~100%之間的某個點。因此說,軟件開發過程當中值不值得寫單元測試這個問題的答案應該無需再多言了。

文章一開始提到的那些不寫單元測試的理由,每每是抱着一個非黑即白的觀點,認爲不寫單元測試的反面就是寫單元測試且覆蓋率近100%。於是會過度誇大寫單元測試的成本(單元覆蓋率100%的代價固然大),選擇短時間利益。

3、我的的作法

下面以我的的小開源項目gbb爲例,囉嗦幾句我本身寫單元測試的習慣。

  • 開源項目必定要寫單元測試!開源項目必定要寫單元測試!開源項目必定要寫單元測試!按照規定,重要的事情得說三遍。除了上文提到的單元測試的好處外,單元測試也是開源項目負責任的一種體現。我花了時間去構思各類狀況下的測試用例,我能爲開源項目質量負責。
  • 不是非得寫完一個函數就必須立馬寫單元測試或者TDD。關於寫單元測試的時機,我通常選擇在完成一個基本功能後寫單元測試,優先覆蓋功能的主體邏輯,一些邊界條件邏輯不會體如今這個階段的單元測試當中。我以爲這個階段也是投入產出比最大的階段。
  • 等功能相對穩定後,再把一些邊界條件邏輯歸入到單元測試當中。這是單元測試覆蓋率提高較大的階段。
  • 最後一個階段是刷數據階段(gbb項目單元測試覆蓋率曲線)。所謂的刷數據階段的主要目標就是爲了讓覆蓋率儘量提升。刷數據並非在某個功能成熟穩定後開始,我是選擇在開源項目進入成熟階段後開始刷單元測試覆蓋率,爲的就是使其更加好看。對於非開源項目,建議選擇跳過這個摳細節的階段。

4、參考

在寫這篇博客時,我並無查閱相關的這類文章。爲的就是防止他人的觀點在不知不覺中摻入其中,影響了個人原始觀點。

相關文章
相關標籤/搜索