1、是什麼
單元測試(Unit Testing)又稱為模組測試,是針對程式模組來進行正確性檢驗的測試工作。
- 程式模組是軟體設計的最小單位,程式單元是應用的最小可測試部件
• 在程序導向程式設計中,一個單元就是單個程式、函式、過程等
• 在物件導向程式設計中,最小單元就是方法,包括基類(超類)、抽象類、或者派生類(子類)中的方法
2、測什麼
並不是所有的專案都需要單元測試,一次性的專案不需要單元測試,持續迭代的產品需要單元測試,通常只有底層模組或者核心模組的測試中才會採用單元測試
並不是所有的“單元”都需要單元測試,服務程式碼、管理者程式碼、儲存程式碼都應該是簡單的順序執行、沒有邏輯的程式碼,不需要單元測試
同理,單元測試的程式碼不需要單元測試——單元測試的程式碼應該只包含簡單的順序執行、沒有邏輯的程式碼
2.1 單元測試規則
必須進行測試的是通用、公共的Utils函式
複雜互動操作需要進行一定的測試
網路請求可以交給系統測試,或者不進行測試
2.2 可測試的程式碼
對於一個邏輯單元(方法),依賴於兩個方面:一個是輸入的引數,另一個是對外部的方法呼叫
只要確保輸入引數不包含外部環境的上下文,同時內部程式碼對外部的呼叫也不包含環境上下文的訪問,這個方法就是可單元測試的
2.3 判斷可測試的程式碼
方法的執行是否需要mock
方法是否可以直接執行
方法的引數是否可以自由模擬,不依賴外部環境
2.4 改造程式碼
如果程式碼裡有邏輯,但是不可單元測試的話,就需要改造程式碼
首先隔離邏輯程式碼和外部環境程式碼,再對邏輯程式碼進行單元測試
3、怎麼測
3.1 單元測試的寫法
透過提供預期的輸入和預期的結果,與單元的實際執行結果進行對比,就可以知道單元的工作是否和預期的一致
各種輸入引數的邊界條件都需要測試到
單元測試的覆蓋率可以幫助識別單元測試是否存在沒有執行到的程式碼
3.2 命名方法
測試程式碼和業務程式碼的組織架構要保持一致,一一對應
單元測試的類名後加Test
單元測試的方法前加test
處於同一包名下,方便訪問protected型別的方法
3.3 單元測試執行
構建輸入引數,並預測該輸入所產生的輸出
呼叫要測試的目標方法,獲取輸出
Assert目標方法的輸出是否和預期的輸出一致
3.3.1 輸入資料
被測試函式的輸入引數
被測試函式內部需要讀取的全域性靜態變數
被測試函式內部需要讀取的成員變數
函式內部呼叫子函式獲得的資料
函式內部呼叫子函式改寫的資料
嵌入式系統中,在中斷呼叫時改寫的資料
3.3.2 預計輸出
被測試函式的返回值
被測試函式的輸出引數
被測試函式所改寫的成員變數
被測試函式所改寫的全域性變數
被測試函式中進行的檔案更新
被測試函式中進行的資料庫更新
被測試函式中進行的訊息佇列更新
3.4 原則
覆蓋分支和迴圈條件的所有路徑
每個理想的測試案例獨立於其它案例,即模組隔離
4、誰來測
單元測試更偏技術,它們通常關注程式碼細節,甚或是程式語言特有的概念,所以編寫單元測試主要應該由研發負責
測試人員更瞭解如何制定測試計劃,根據特定分析,如等價類劃分和邊界值分析,定義有價值的值。因此,程式設計師需要從測試人員那裡“竊取”這類知識,
或者,他們可以和測試人員結對,一起討論需要編寫的測試,但是,之後應該由程式設計師實現它們
結對是最好的選擇,因為測試人員和程式設計師可以更好地互相學習,擴充自己的知識面
5、何時測
開發過程中,單元測試應該來測試那些可能會出錯的地方,或是那些邊界情況
維護過程中,單元測試應該跟著QA的bug report來走,每一個bug都應該有個單元測試。
於是研發就會對自己的程式碼變更有兩個自信,一是bug被fixed,二是相同的bug不會再次出現
6、怎麼測
團隊制度,單元測試是團隊成熟度的基本標誌
把單元測試執行、程式碼覆蓋率統計和持續整合流水線做整合,以確保每次程式碼遞交,都會自動觸發單元測試,並在單元測試執行過程中自動統計程式碼覆蓋率,
最後以“單元測試透過率”和“程式碼覆蓋率”為標準來決定本次程式碼遞交是否能夠被接受。
7、侷限
單元測試只測試程式單元自身的功能
單元測試只能表明測到的問題,不能表明不存在未測試到的錯誤
單元測試不能發現整合錯誤、效能問題、或者其他系統級別的問題,結合其他軟體測試活動更為有效
研發可以從QA那裡學習一些測試用例的基本概念。
單元測試還要考慮成本和收益。
軟體的質量不是測試出來的,而是設計和維護出來的。