阿里Java開發手冊部分加註——單元測試
三、單元測試
1.【強制】好的單元測試必須遵守 AIR 原則。
說明:單元測試在線上執行時,感覺像空氣(AIR)一樣並不存在,但在測試質量的保障上,卻是非常關鍵的。好的單元測試巨集觀上來說,具有自動化、獨立性、可重複執行的特點。
A:Automatic(自動化)
I:Independent(獨立性)
R:Repeatable(可重複)
2.【強制】單元測試應該是全自動執行的,並且非互動式的。測試用例通常是被定期執行的,執行過程必須完全自動化才有意義。輸出結果需要人工檢查的測試不是一個好的單元測試。單元測試中不準使用 System.out 來進行人肉驗證,必須使用 assert 來驗證。
public class AssertTest
{
public static void main(String[] args)
{
AssertTest at = new AssertTest();
at.assertMe(true);
at.assertMe(false);
}
private void assertMe(boolean boo)
{
String s = null;
assert boo?true:false:s = "hello world";
System.out.println("true condition");
}
}執行的時候會得到這樣的結果
true condition
Exception in thread "main" java.lang.AssertionError: hello world
at AssertTest.assertMe(AssertTest.java:14)
at AssertTest.main(AssertTest.java:7)
3.【強制】保持單元測試的獨立性。為了保證單元測試穩定可靠且便於維護,單元測試用例之間決不能互相呼叫,也不能依賴執行的先後次序。
反例:method2 需要依賴 method1 的執行,將執行結果作為 method2 的輸入。
4.【強制】單元測試是可以重複執行的,不能受到外界環境的影響。
說明:單元測試通常會被放到持續整合中,每次有程式碼 check in 時單元測試都會被執行。如果單測對外部環境(網路、服務、中介軟體等)有依賴,容易導致持續整合機制的不可用。
正例:為了不受外界環境影響,要求設計程式碼時就把 SUT 的依賴改成注入,在測試時用 spring 這樣的 DI 框架注入一個本地(記憶體)實現或者 Mock 實現。
注:中介軟體:
中介軟體是一種獨立的系統軟體或服務程式,分散式應用軟體藉助這種軟體在不同的技術之間共享資源。中介軟體位於客戶機/ 伺服器的作業系統之上,管理計算機資源和網路通訊。是連線兩個獨立應用程式或獨立系統的軟體。相連線的系統,即使它們具有不同的介面,但通過中介軟體相互之間仍能交換資訊。執行中介軟體的一個關鍵途徑是資訊傳遞。通過中介軟體,應用程式可以工作於多平臺或OS環境。如,主機板可溝通U盤、磁碟、光碟的不同介面,進行資料分享。
分散式計算環境(Distributed Computing Environment):
DCE目標是,為分散式應用程式提供一個完整、緊密的通用環境,不論使用什麼機器、作業系統和網路,只要加上DCE軟體都可以執行。最簡單的分散式構成:負載均衡伺服器Load Balance(如Nginx),Web伺服器Web Server(如Tomcat),快取伺服器Cache Server,(如memcache),以及共享資料庫(如Mysql),就可供客戶端Client呼叫了。
5.【強制】對於單元測試,要保證測試粒度足夠小,有助於精確定位問題。單測粒度至多是類級別,一般是方法級別。
說明:只有測試粒度小才能在出錯時儘快定位到出錯位置。單測不負責檢查跨類或者跨系統的互動邏輯,那是整合測試的領域。
6.【強制】核心業務、核心應用、核心模組的增量程式碼確保單元測試通過。
說明:新增程式碼及時補充單元測試,如果新增程式碼影響了原有單元測試,請及時修正。
7.【強制】單元測試程式碼必須寫在如下工程目錄:src/test/java,不允許寫在業務程式碼目錄下。
說明:原始碼構建時會跳過此目錄,而單元測試框架預設是掃描此目錄。
8.【推薦】單元測試的基本目標:語句覆蓋率達到 70%;核心模組的語句覆蓋率和分支覆蓋率都要達到 100%。
說明:在工程規約的應用分層中提到的 DAO 層,Manager 層,可重用度高的 Service,都應該進行單元測試。
9.【推薦】編寫單元測試程式碼遵守 BCDE 原則,以保證被測試模組的交付質量。
B:Border,邊界值測試,包括迴圈邊界、特殊取值、特殊時間點、資料順序等。
C:Correct,正確的輸入,並得到預期的結果。
D:Design,與設計文件相結合,來編寫單元測試。
E:Error,強制錯誤資訊輸入(如:非法資料、異常流程、非業務允許輸入等),並得到預期的結果。
10.【推薦】對於資料庫相關的查詢,更新,刪除等操作,不能假設資料庫裡的資料是存在的,或者直接操作資料庫把資料插入進去,請使用程式插入或者匯入資料的方式來準備資料。
反例:刪除某一行資料的單元測試,在資料庫中,先直接手動增加一行作為刪除目標,但是這一行新增資料並不符合業務插入規則,導致測試結果異常。
11.【推薦】和資料庫相關的單元測試,可以設定自動回滾機制,不給資料庫造成髒資料。或者
對單元測試產生的資料有明確的前後綴標識。
正例:在 RDC (Reliability Data Contro,可靠性資料控制)內部單元測試中,使用 RDC_UNIT_TEST_的字首標識資料。
12.【推薦】對於不可測的程式碼建議做必要的重構,使程式碼變得可測,避免為了達到測試要求而書寫不規範測試程式碼。
13.【推薦】在設計評審階段,開發人員需要和測試人員一起確定單元測試範圍,單元測試最好覆蓋所有測試用例。
14.【推薦】單元測試作為一種質量保障手段,不建議專案釋出後補充單元測試用例,建議在專案提測前完成單元測試。
15.【參考】為了更方便地進行單元測試,業務程式碼應避免以下情況:
構造方法中做的事情過多。
存在過多的全域性變數和靜態方法。
存在過多的外部依賴。
存在過多的條件語句。
說明:多層條件語句建議使用衛語句、策略模式、狀態模式等方式重構。
16.【參考】不要對單元測試存在如下誤解:
那是測試同學乾的事情。本文是開發手冊,凡是本文內容都是與開發同學強相關的。
單元測試程式碼是多餘的。系統的整體功能與各單元部件的測試正常與否是強相關的。
單元測試程式碼不需要維護。一年半載後,那麼單元測試幾乎處於廢棄狀態。
單元測試與線上故障沒有辯證關係。好的單元測試能夠最大限度地規避線上故障。