開發需要寫單元測試嗎?

網上看到有個吐槽ThoughtWorks面試的帖子,說因為單元測試寫的不好所以被拒。

而我目前所在的單位,是沒有單元測試的。而且好像從網上看,好多初創公司(小公司)基本上也都沒有要求單元測試,基本上就是開發做完了,直接扔給測試,然後好多測試也就是點點功能,也就算測完了。

所以很疑惑,單元測試是必須的嗎?好處在哪裡?

@vczh 召喚大神,等待解惑



第一個問題應該是,這個公司需要(覆蓋率比較高的)測試么?

對於大部分公司來說,他們的選擇都是不寫。為什麼?

首先,他們的產品fail了影響不大。尤其是網頁開發,網頁崩了,顯示對不齊了,移動端看不見內容了,這根本不是個事兒。用戶早就習慣了網頁不完全按照他們理想的狀態工作了。因此對於這些公司來說,有必要把精力放在大規模的測試上么?完全沒有。試試新功能在自己的瀏覽器下好不好使就可以上線了,上去了有bug大家也不會在意。

其次,他們的產品更新速度快。更新速度是個雙刃劍,比如對於網頁端的開發來說,更新產品難度極低,發現了bug可以隨時修復。同時更新的feature比更穩定的工作環境對於他們的產品更重要。所以很多人覺得自己寫代碼就是在寫bug,修復了之前的一些bug,把更多的bug跟著新的feature加進去,未來再修復。反正發現了可以隨時修復嘛。這裡說一句題外話,Tesla的firmware update想法非常牛,節省了海量召回成本。但是在固件如此容易更新的情況下,是否Tesla會降低對出廠產品穩定性的要求,從而讓新的feature更快地面世?不得不說是個隱患。

第三,他們窮。當你的錢只夠開發或者測試的時候,你選什麼?對於大部分小企業來說這是實實在在的問題。他們恨不得雇一個碼農來實現他們偉大的想法,把碼農當工地的工人,自己是設計高樓大廈的建築師。最後的結果當然是碼農只有經歷做feature開發,而沒有精力去做大規模測試。

然後才應該是,這個測試,應該讓誰寫。

我覺得比較合理的方法應該是開發自己寫一份初稿,然後測試去完善。為什麼初稿要開發去寫?因為開發者對自己的程序了解程度是最深的,他最清楚自己的程序在哪些corner case容易出錯,也最了解哪些feature應該被測試。如果寫完直接扔給測試,那測試要從頭理解他的代碼,很可能還理解上有偏差,完全是事倍功半。

但是如果讓開發去完整地寫一個test,第一浪費開發的時間,第二每個開發對測試系統的了解也不夠透徹,很可能大家的test長得千奇百怪的。這個部分恰好是測試擅長的。當測試知道了這個單元的大致測試方向,他可以更好地對接測試系統,把測試寫得高效,同時有有效的log信息。

最後說說單元測試。

單元測試這個東西,還是要看你以什麼為一個「單元」。對於大部分公司來說,對每一個函數進行「單元測試」的價值都是偏低的。但是如果你有一個比較獨立的功能(當然也可能這個功能就一個函數),應該對這個功能進行比較詳盡的測試。

當然也要看你對產品的穩定性需求。比如Compiler這種東西,那是真的每個標準函數都要寫單元測試的。。


單元測試最大的好處就是這種測試的「單元性」。你想想如果你不寫單元測試,然後你又給程序增加了一個新的模塊(比如說一個函數也可以算一個模塊),這個時候怎麼知道寫對沒呢?肯定會把程序跑起來,然後操作一下看看。

這種方法實際上屬於系統測試。系統測試毫無疑問是必須的,但如果靠它來排查錯誤,是非常耗費時間的。主要原因,一是測試代價大,必須把各個模塊合起來成為一個系統啟動後才能測試;二是測試覆蓋難,要想測試某個模塊被調用時的各種情形,難度很大,因為從用戶操作到最終觸發某個模塊之間,調用鏈條可能很長,或者模擬起來代價特別大。

單元測試就是解決這個痛點的。你不需要啟動整個系統,就可以直接的,針對性的對任意模塊進行測試。而且可以簡單的模擬各種情況覆蓋其各種分支。這是降低整體開發時間,提高軟體質量的一種有效方法。

具體怎麼做單元測試,和問題無關,也就不討論了。這方面的書很多。


這居然是個問題??


正確性有兩種驗證方式:形式化證明和單元測試,自己選吧。


簡單說一下:

1. 公用組件庫,SDK,所有公共開發的基礎部分,都需要有嚴格的單元測試保證,而且這些東西變更不會特別頻繁,所以覆蓋率需要100%。

2. 業務項目,需要自動化介面功能測試,不需要單元測試,一個是成本太高,而是變化太快,並無必要。(PS:沒有測試工程師的團隊除外)另外,業務feature代碼,都要經過師兄的詳細 review!加上測試工程師的全功能回歸,一定程度上代替了單元測試的功能。

單測要因人而異!不要為了聽起來高大上就要做單測!最終目的就是保證項目質量,而不是炫技,畢竟單測並沒有什麼技術含量!


不寫測試就無法重構

無法重構代碼就會變爛

所以不寫測試代碼就會爛掉。


要!

我覺得寫出精妙易維護的自動化程度高的UT代碼要比寫真正的代碼難。如果不覺得,那麼估計寫UT代碼經驗不足。


如果你告訴你老闆說寫一個基本完全覆蓋的測試需要將工期延長一倍,你問問你老闆願不願意讓你寫測試吧。


說一下我工作的情況吧。

基本上是這樣子的從第一家公司到最後一家公司,我沒有任何一家公司可以做到單元測試覆蓋率到20%的情況。

其中各有各的原因我一一來列舉。

第一家公司剛過去的時候,業務已經成型。測試代碼只有大概100行左右,佔到整個業務代碼都不到0.1%,所以即使我想用測試的方法也沒有什麼意義。

我雖然一直覺得測試是非常重要的,我覺得測試和生產代碼的比例達到1:1的比例比較合理的。但這即使在一個從0到1的產品開發過程中也依然沒有推行下去。

這個原因主要是測試資料庫的準備以及測試資料庫的初始數據的載入問題。

最開始使用clojure的時候,大家習慣了使用repl的方式來做開發,再加上稍微使用一下宏就可以列印出很多調試信息。這個比寫測試代碼「省時省力」多了。這種環境中基本很難讓大家形成需要寫測試代碼的習慣。大家的基本想法僅僅是完成現有業務而已。同時又因為沒有一個非常成熟的業內實踐,大部分有副作用的函數都是與資料庫相關的。這個需要較為合理的載入測試數據,mock測試函數,事務回滾機制。最頭疼的事情是系統依賴第三方支付。簡單一個事例,用戶開戶操作不能成功執行兩次,第一次返回成功,第二次就會異常,返回重複開戶。導致單元測試基本屬於形同虛設。

最近的項目使用就spring框架,有junit+mockio,整個測試的生態都非常完備,而且又是從0開始的項目,理應可以推行好單元測試。但即使是這樣,依然沒有,把測試覆蓋率達到20%。在項目開始時由於交付時間的壓力,導致大家都有些偷懶。整個技術團隊如果不實行單元測試,那麼基本就沒有辦法開展了。比如,前端開發不做單測,後端做,會導致項目進度壓在後端身上,同理。

大家在追求「快速交付」的前提下,代碼質量這件事情就推脫給了QA。這件事情的嚴重後果就是沒有人對這個系統有足夠的把握它會運行正常。

後期時間稍微充裕的時候,我提倡大家在團隊內部做單元測試的補充,盡量覆蓋到之前的代碼代碼,基本沒有人會實行。

總結一下這些都是血淚教訓:

1.單元測試應該配合代碼審查在團隊中,有人沒有在做充足的單元測試的時候可以拒絕審查。

2.單元測試需要從開發的第一天就算起

3.技術團隊都需要單元測試,前端,後端都需要。

4.追求短期的快速交付會帶來後續的長期的問題,總體上時間花銷更大

5.避免讓大家有完成業務需求就好了的態度


我是QA。我們有刀。請自重。


-

動態語言不寫單元測試, 科科

多說一句, 寫測試跟寫業務代碼一樣. 有些人就是體力活, 有些人就是在創作

-


手頭開發項目時進行了TDD,發現它非常好用,具體表現在如下方面:

1.引導程序員設計合理的功能粒度和易測的外部模塊介面。

2.自動化測試,能夠在保證質量的前提下進行重構,對代碼進行修改後可以方便地運行單元測試,以保證代碼沒有改成屎。

3.測試用例可以作為api demo文檔,團隊內程序員問我某個工具類的API如何使用,我讓他去看單元測試的API調用方法。

4.提高開發速度,雖然測試代碼是業務邏輯代碼量的2-3倍,但是減少了大量基本邏輯錯誤,減少了返工工作量;減少調試時間。


不給自己的代碼寫單元測試的程序猿都是流氓程序猿


當然!

但是並不是所有代碼都能或者都適合寫單元測試,寫單元測試一個重要前提是被測試代碼要做好功能獨立和模塊解耦,否則將是很痛苦的!


你準備讓誰寫?


對於敏捷來講,尤其那些亂用敏捷的所謂互聯網公司,業務代碼迭代做 TDD 或者 BDD 估計是會把你帶到另一個坑裡去,而且會被認為 ROI 比較低,你願意做,你的上級未必希望你去做。不過,對於有了一定規模的公司,在構建基礎設施的時候,那是必須要做的,至少我們目前是這麼搞的


不寫單元測試的代碼沒人敢重構。後果是後面代碼越來越難加,越來越多難維護。誰想重構只要想到出問題了老闆吼過來:「本來好好的,你為什麼要去改他?」


優秀的程序員寫,碼農不寫.


這麼說吧,直接上圖

請看這本書

剛看過


推薦閱讀:

在開發中,說下你奇葩的排錯思路,解決問題的巧妙方法?
究竟是c++的發展進入了邪路,還是我寫代碼的姿勢不正確?
哪些公司的哪些團隊有嚴格的 code review?
軟體開發行業相關的介紹?小白成長起來需要多少東西?

TAG:測試 | 軟體開發 | 編程 |