單元測試及最佳實踐

前言

鏡子迷宮

在工做中或者在面試中,我常常碰到的開發人員就是對單元測試不重視,這一類基本上都表現出了一種「無知的自信」,總以爲本身寫的代碼質量很高,直到一次次蟲子(Bug)把本身咬的頭破血流時,才發現原來本身的代碼已經到了剪不斷理還亂的狀態,而每一次修改一個bug,都須要走一遍「墨鏡迷宮」 (看上圖)。還有不少人知道單元測試或者寫出了單元測試,可是就是寫了一個方法,上面標註了一個[Test]屬性而已,甚至不少的人單元測試上面標註的是[IgnoreTest], 每次看見這些,我都深深的感到推行單元測試之路是艱難的,是遙遠的,可是我依然堅信是是渴望也可及的,只要有着深深的信念,堅強的意志,無謂的勇氣,一頭扎進去泥巴堆裏,假以時日,當大雨來臨,必將帶走泥巴,今後你拔劍揚眉,哦,你不用拔劍了,由於你就是劍。。。前端

爲了讓更多人可以拔劍揚眉,也爲了咱們公司剛入職的新人作一些培訓,我精心準備了單元測試的一些知識,在此爲你奉上,我儘可能用簡短的語句來描述,若是你不清楚我說的某一些點,那麼歡迎你發郵件給我 wangdeshui@outlook.com,我能夠針對集中的點發篇文章,若是你想知道我說的全部點怎麼實踐,那就聯繫我,試試加入到咱們公司來。面試

什麼是單元測試

單元測試是開發者編寫的一小段代碼,用於檢驗被測代碼中的一個很明確的功能是否正確。一般而言,一個單元測試是用於判斷某個特定條件(或者場景)下某個特定函數的行爲。數據庫

執行單元測試,是爲了證實某段代碼的行爲確實和開發者所指望的一致。所以,咱們所要測試的是規模很小的、很是獨立的功能片斷。經過對全部單獨部分的行爲創建起信心。而後,才能開始測試整個系統。編程

爲何要使用單元測試

  • 單元測試使工做完成的更輕鬆
  • 單元測試使你的設計更好
  • 大大減小花在調試上的時間
  • 能幫助你更好的理解代碼

沒有單元測試

  • 任何代碼都是在假定其餘代碼是正確無誤的狀況下編寫的。
  • 修改一處代碼時沒法得知會對其餘代碼產生怎樣的影響。
  • 任何一處改動都須要進行功能級別的總體調試。

單元測試難以推進的緣由

太花時間

不少人認爲單元測試很花時間,可是想一想咱們在下面幾點話的時間,我常常看到爲了測試一個簡單的API方法,咱們不少人必須讓前端跑起來,甚至本身寫一個客戶端才能調用網絡

  • 調試上花的時間
  • 對自認爲正確的代碼,花了多少時間確認代碼是正確的。
  • 定位Bug所耗的時間

測試不是個人工做

不少人認爲測試不是本身的工做,可是想想每次測試提出一個bug所花的時間,以及你改bug所化的時間,因此下面2點是很重要dom

  • 內在質量的重要性
  • 測試應該是輔助,好的軟件是開發設計出來的,不是測試出來的

系統可測試性差

  • 系統耦合度很高,咱們須要提升咱們的團隊的設計能力。

單元測試最佳實踐

實踐一: 三到五步

  • SetUp
  • 輸入
  • 調用
  • 輸出
  • TearDown

實踐二: 運行快速

爲何?

單元測試運行很頻繁,是輔助開發的,在開發過程當中運行,若是慢影響很大函數

多快較好?

  • 單個測試小於200ms
  • 單個測試套件小於10s
  • 整個測試小於10分鐘

實踐三:一致性

任什麼時候候一樣的輸入須要一樣的結果工具

Date date=new Date()
    Random.next()

這樣的代碼都須要Mock掉,否則時間每次都不一樣,結果就會不同。post

實踐四:原子性

** 全部的測試只有兩種結果:成功和失敗**
不能部分測試經過單元測試

實踐五:單一職責

一個測試只驗證一個行爲

** 測試行爲,不要測試方法 **

  • 一個方法,多個行爲    ----->  多個測試
  • 一個行爲,多個方法   -----   一個測試
    這裏的一個行爲,多個方法通常指這個方法調用private, protected, getters, setters
  • 多個Assert只有在測試同一個行爲時能夠接受

實踐六:獨立無耦合

單元測試之間無相互調用

  • 單元測試執行順序無關
  • 不一樣的順序無影響

單元測試之間不能共享狀態

好比一個測試裏設置了一個屬性值,而後在另一個測試裏用,若是必須共享能夠放到Setup裏

實踐七:隔離外部調用

  • 單元測試須要快速運行,且每次結果一致,因此須要隔離一切對外部的調用。
  • 不使用具體的其它真實類,就是不要new
  • 不讀數據庫
  • 不讀網絡
  • 不讀外部文件
  • 適當時候能夠構造一個相同的內部文件來Mock
  • 不依賴本地時間
  • 不依賴環境變量

實踐八: 自描述

  • 單元測試是開發級文檔
  • 單元測試是方法的描述
    單元測試自描述命名

實踐九: 單元測試邏輯

  • 單元測試必須容易讀和理解的
  • 變量名,方法名,類名
  • 無條件語句,無Switch
    辦法:分解if到多個測試,全部的輸入都是已知的,全部的結果都是必定的(Mock)
  • 無循環語句
  • 無異常捕捉
    ** 測試預知的異常,用ExpectedException方法 **

實踐十: 斷言

  • 斷言信息最好包含Business Information
  • 斷言信息包含出錯的具體信息若是失敗
  • 適當時候能夠封裝本身的Assert
    好比:

    Assert.IsProgrammer(Jack)
    Return Jack. Cancooking() && Jack.CanCoding()

實踐十一:產品代碼

  • 產品代碼無測試邏輯
    不能有:

  If(global.IsTest){…}

  • 測試代碼和產品代碼要分離
  • 不要在產品代碼裏有任何只供測試用的代碼
  • 使用依賴注入

最後,單元測試經常使用技術及工具

下面是.NET程序經常使用的單元測試須要的技術和工具,其它語言請自信比對。

  • 面向接口編程
  • 依賴注入(Castle, Unity, Ninject)
  • Moq
  • 測試工具(xUnit) 
  • .Net Nunit
  • 代碼覆蓋率測試工具Ncover
  • 自動運行測試輔助工具NCrunch
相關文章
相關標籤/搜索