单元测试系列一-为什么要写单元测试,何时写,写多细
一、前言
半年前在公司團隊內推動單元測試的落地,略有一些心得,記錄在此。如有不同觀點或建議,請在評論區(qū)留言,一起探討。
定義:單元測試是用來對一個模塊、一個函數(shù)或者一個類來進行正確性檢驗的測試工作。
單元測試從長期來看,可以提高代碼質量,減少維護成本,降低重構難度。但是從短期來看,加大了工作量,對于進度緊張的項目中的開發(fā)人員來說,可能會成為不少的負擔。
本文從為什么要寫單元測試,何時寫,寫多細這些我們最關心的問題展開討論,試圖解答如何在進度緊張的項目中,通過寫有效的單元測試來提高代碼質量的問題。
二、單元測試要寫多細
酷殼上有篇關于“單元測試要做多細”的文章,文章是從StackOverflow上的一個問題討論開的。這個問題是–
“TDD需要花時間寫測試,而我們一般多少會寫一些代碼,而第一個測試是測試我的構造函數(shù)有沒有把這個類的變量都設置對了,這會不會太過分了? 那么,我們寫單元測試的這個單元的粒度到底是什么樣的?并且,是不是我們的測試測試得多了點?”點贊最多的答案是–
老板為我的代碼付報酬,而不是測試,所以,我對此的價值觀是——測試越少越好,少到你對你的代碼質量達到了某種自信(我覺得這種的自信標準應該要高于業(yè)內的標準,當然,這種自信也可能是種自大)。如果我的編碼生涯中不會犯這種典型的錯誤(如:在構造函數(shù)中設了個錯誤的值),那我就不會測試它。我傾向于去對那些有意義的錯誤做測試,所以,我對一些比較復雜的條件邏輯會異常地小心。當在一個團隊中,我會非常小心的測試那些會讓團隊容易出錯的代碼。這個答案給人感覺對單元測試持一定的否定態(tài)度和不感冒態(tài)度,但是這一最佳答案的回答者是Kent Beck!正是那位極限編程、測試驅動開發(fā)和單元測試以及JUnit的創(chuàng)造者Kent Beck。Kent Beck的答案,正好回答了單元測試要寫到什么程度這個問題。單元測試不是越多越好,而是越有效越好!進一步解讀就是哪些代碼需要有單元測試覆蓋:
1. 邏輯復雜的
2. 容易出錯的
3. 不易理解的,即使是自己過段時間也會遺忘的,看不懂自己的代碼,單元測試代碼有助于理解代碼的功能和需求
4. 公共代碼。比如自定義的所有http請求都會經(jīng)過的攔截器;工具類等。
5. 核心業(yè)務代碼。一個產品里最核心最有業(yè)務價值的代碼應該要有較高的單元測試覆蓋率。
三、何時寫單元測試
寫單元測試的時機不外乎三種情況:
(1)一是在具體實現(xiàn)代碼之前,這是測試驅動開發(fā)(TDD)所提倡的;
(2)二是與具體實現(xiàn)代碼同步進行。先寫少量功能代碼,緊接著寫單元測試(重復這兩個過程,直到完成功能代碼開發(fā))。其實這種方案跟第一種已經(jīng)很接近,基本上功能代碼開發(fā)完,單元測試也差不多完成了。
(3)三是編寫完功能代碼再寫單元測試。我的實踐經(jīng)驗告訴我,事后編寫的單元測試“粒度”都比較粗。對同樣的功能代碼,采取前兩種方案的結果可能是用10個“小”的單測來覆蓋,每個單測比較簡單易懂,可讀性可維護性都比較好(重構時單測的改動不大);而第三種方案寫的單測,往往是用1個“大”的單測來覆蓋,這個單測邏輯就比較復雜,因為它要測的東西很多,可讀性可維護性就比較差。
建議:我個人是比較推薦單元測試與具體實現(xiàn)代碼同步進行這個方案的。只有對需求有一定的理解后才能知道什么是代碼的正確性,才能寫出有效的單元測試來驗證正確性,而能寫出一些功能代碼則說明對需求有一定理解了。
四、為什么要寫單元測試
這其實是問單元測試能帶來什么好處。之所以把這個問題放在最后討論是因為如果一上來就說單元測試多好多好,終究還是會缺乏說服力。
而有了上面討論做鋪墊,我們更加清楚單元測試的使用場景,以及它做得到和做不到的。
單元測試的作用:
(1)讓我們對自己的代碼有信心
修改了代碼后單測依然通過的,起碼說明我們的修改沒有破壞程序的正確性。這從主觀上能增加我們對代碼的信心。雖然單元測試通過了并不意味著程序就沒有bug了,但我們也要了解到這可能不是單元測試的問題。單元測試顧名思義是測試一個”單元”,這個”單元”一般是類或方法,而不是整個系統(tǒng)。對整個系統(tǒng)的測試那是集成測試,功能測試的職責。單元測試追求的是快速反饋,頻繁執(zhí)行。集成測試雖然測“全局”,但成本較高,所以執(zhí)行頻率較少。兩者使用場景不同,目的不同。
(2)為代碼重構保駕護航
看到代碼很差勁,想重構,但又擔心重構之后出問題,怎么辦呢?如果有單元測試情況就不一樣了,重構完代碼,跑一遍單元測試,如果單元測試都通過,基本上可以保證我們的重構沒有破壞原來代碼邏輯的正確性。不過前提是之前的寫的單元測試質量很好,覆蓋率很高。當然這僅限于小范圍的重構,比如重構一個類或者函數(shù)的實現(xiàn),但對于大刀闊斧的重構(比如單體重構成微服務,面向庫表模式重構成DDD),就不適用,那個時候要重寫單元測試了。
(3)通過單元測試快速熟悉代碼
單元測試不僅起到了測試的作用,還是一種很好的“文檔”,通過單元測試,我們不需要深入的閱讀代碼,便能知道這段代碼做什么工作,有哪些特殊情況需要考慮,包含哪些業(yè)務。
五、小結
何時寫
單元測試與具體實現(xiàn)代碼同時進行。寫多細
哪些代碼需要有單元測試覆蓋:
1、邏輯復雜的
2、容易出錯的
3、不易理解的,即使是自己過段時間也會遺忘的,看不懂自己的代碼,單元測試代碼有助于理解代碼的功能和需求
4、公共代碼。比如自定義的所有http請求都會經(jīng)過的攔截器;工具類等。
5、 核心業(yè)務代碼。一個產品里最核心最有業(yè)務價值的代碼應該要有較高的單元測試覆蓋率。
總結
以上是生活随笔為你收集整理的单元测试系列一-为什么要写单元测试,何时写,写多细的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python-.item()的理解与使用
- 下一篇: 代码设置textField和textVi