\1. 【強(qiáng)制】好的單元測(cè)試必須遵守 AIR 原則。
說(shuō)明:?jiǎn)卧獪y(cè)試在線上運(yùn)行時(shí),感覺(jué)像空氣(AIR)一樣感覺(jué)不到,但在測(cè)試質(zhì)量的保障上,卻是非常關(guān)鍵的。好的單元測(cè)試宏觀上來(lái)說(shuō),具有自動(dòng)化、獨(dú)立性、可重復(fù)執(zhí)行的特點(diǎn)。
? A:Automatic(自動(dòng)化)
? I:Independent(獨(dú)立性)
? R:Repeatable(可重復(fù))
\2. 【強(qiáng)制】單元測(cè)試應(yīng)該是全自動(dòng)執(zhí)行的,并且非交互式的。測(cè)試用例通常是被定期執(zhí)行的,執(zhí)行過(guò)程必須完全自動(dòng)化才有意義。輸出結(jié)果需要人工檢查的測(cè)試不是一個(gè)好的單元測(cè)試。單元測(cè)試中不準(zhǔn)使用 System.out
來(lái)進(jìn)行人肉驗(yàn)證,必須使用 assert
來(lái)驗(yàn)證。
\3. 【強(qiáng)制】保持單元測(cè)試的獨(dú)立性。為了保證單元測(cè)試穩(wěn)定可靠且便于維護(hù),單元測(cè)試用例之間決不能互相調(diào)用,也不能依賴執(zhí)行的先后次序。
反例:method2
需要依賴 method1
的執(zhí)行,將執(zhí)行結(jié)果作為 method2
的輸入。
\4. 【強(qiáng)制】單元測(cè)試是可以重復(fù)執(zhí)行的,不能受到外界環(huán)境的影響。
說(shuō)明:?jiǎn)卧獪y(cè)試通常會(huì)被放到持續(xù)集成中,每次有代碼 check in 時(shí)單元測(cè)試都會(huì)被執(zhí)行。如果單測(cè)對(duì)外部
環(huán)境(網(wǎng)絡(luò)、服務(wù)、中間件等)有依賴,容易導(dǎo)致持續(xù)集成機(jī)制的不可用。
正例:為了不受外界環(huán)境影響,要求設(shè)計(jì)代碼時(shí)就把 SUT 的依賴改成注入,在測(cè)試時(shí)用 spring 這樣的 DI 框架注入一個(gè)本地(內(nèi)存)實(shí)現(xiàn)或者 Mock 實(shí)現(xiàn)。
\5. 【強(qiáng)制】對(duì)于單元測(cè)試,要保證測(cè)試粒度足夠小,有助于精確定位問(wèn)題。單測(cè)粒度至多是類(lèi)級(jí)別,一般是方法級(jí)別。
說(shuō)明:只有測(cè)試粒度小才能在出錯(cuò)時(shí)盡快定位到出錯(cuò)位置。單測(cè)不負(fù)責(zé)檢查跨類(lèi)或者跨系統(tǒng)的交互邏輯,那是集成測(cè)試的領(lǐng)域。
\6. 【強(qiáng)制】核心業(yè)務(wù)、核心應(yīng)用、核心模塊的增量代碼確保單元測(cè)試通過(guò)。
說(shuō)明:新增代碼及時(shí)補(bǔ)充單元測(cè)試,如果新增代碼影響了原有單元測(cè)試,請(qǐng)及時(shí)修正。
\7. 【強(qiáng)制】單元測(cè)試代碼必須寫(xiě)在如下工程目錄:src/test/java,不允許寫(xiě)在業(yè)務(wù)代碼目錄下。
說(shuō)明:源碼編譯時(shí)會(huì)跳過(guò)此目錄,而單元測(cè)試框架默認(rèn)是掃描此目錄。
\8. 【推薦】單元測(cè)試的基本目標(biāo):語(yǔ)句覆蓋率達(dá)到 70%;核心模塊的語(yǔ)句覆蓋率和分支覆蓋率都要達(dá)到 100%
說(shuō)明:在工程規(guī)約的應(yīng)用分層中提到的 DAO 層,Manager 層,可重用度高的 Service,都應(yīng)該進(jìn)行單元測(cè)試。
\9. 【推薦】編寫(xiě)單元測(cè)試代碼遵守 BCDE 原則,以保證被測(cè)試模塊的交付質(zhì)量。
? B:Border,邊界值測(cè)試,包括循環(huán)邊界、特殊取值、特殊時(shí)間點(diǎn)、數(shù)據(jù)順序等。
? C:Correct,正確的輸入,并得到預(yù)期的結(jié)果。
? D:Design,與設(shè)計(jì)文檔相結(jié)合,來(lái)編寫(xiě)單元測(cè)試。
? E:Error,強(qiáng)制錯(cuò)誤信息輸入(如:非法數(shù)據(jù)、異常流程、業(yè)務(wù)允許外等),并得到預(yù)期的結(jié)果。
10.【推薦】對(duì)于數(shù)據(jù)庫(kù)相關(guān)的查詢,更新,刪除等操作,不能假設(shè)數(shù)據(jù)庫(kù)里的數(shù)據(jù)是存在的,或者直接操作數(shù)據(jù)庫(kù)把數(shù)據(jù)插入進(jìn)去,請(qǐng)使用程序插入或者導(dǎo)入數(shù)據(jù)的方式來(lái)準(zhǔn)備數(shù)據(jù)。
反例:刪除某一行數(shù)據(jù)的單元測(cè)試,在數(shù)據(jù)庫(kù)中,先直接手動(dòng)增加一行作為刪除目標(biāo),但是這一行新增數(shù)據(jù)并不符合業(yè)務(wù)插入規(guī)則,導(dǎo)致測(cè)試結(jié)果異常。
11.【推薦】和數(shù)據(jù)庫(kù)相關(guān)的單元測(cè)試,可以設(shè)定自動(dòng)回滾機(jī)制,不給數(shù)據(jù)庫(kù)造成臟數(shù)據(jù)。或者對(duì)單元測(cè)試產(chǎn)生的數(shù)據(jù)有明確的前后綴標(biāo)識(shí)。
正例:在阿里巴巴企業(yè)智能事業(yè)部的內(nèi)部單元測(cè)試中,使用 *ENTERPRISE_INTELLIGENCE _UNIT_TEST_*
的前綴來(lái)標(biāo)識(shí)單元測(cè)試相關(guān)代碼。
12.【推薦】對(duì)于不可測(cè)的代碼在適當(dāng)?shù)臅r(shí)機(jī)做必要的重構(gòu),使代碼變得可測(cè),避免為了達(dá)到測(cè)試要求而書(shū)寫(xiě)不規(guī)范測(cè)試代碼。
13.【推薦】在設(shè)計(jì)評(píng)審階段,開(kāi)發(fā)人員需要和測(cè)試人員一起確定單元測(cè)試范圍,單元測(cè)試最好覆蓋所有測(cè)試用例(UC)。
14.【推薦】單元測(cè)試作為一種質(zhì)量保障手段,在項(xiàng)目提測(cè)前完成單元測(cè)試,不建議項(xiàng)目發(fā)布后補(bǔ)充單元測(cè)試用例。
15.【參考】為了更方便地進(jìn)行單元測(cè)試,業(yè)務(wù)代碼應(yīng)避免以下情況:
? 構(gòu)造方法中做的事情過(guò)多。
? 存在過(guò)多的全局變量和靜態(tài)方法。
? 存在過(guò)多的外部依賴。
? 存在過(guò)多的條件語(yǔ)句。
說(shuō)明:多層條件語(yǔ)句建議使用衛(wèi)語(yǔ)句、策略模式、狀態(tài)模式等方式重構(gòu)。
16.【參考】不要對(duì)單元測(cè)試存在如下誤解:
? 那是測(cè)試同學(xué)干的事情。本文是開(kāi)發(fā)手冊(cè),凡是本文內(nèi)容都是與開(kāi)發(fā)同學(xué)強(qiáng)相關(guān)的。
? 單元測(cè)試代碼是多余的。系統(tǒng)的整體功能與各單元部件的測(cè)試正常與否是強(qiáng)相關(guān)的。
? 單元測(cè)試代碼不需要維護(hù)。一年半載后,那么單元測(cè)試幾乎處于廢棄狀態(tài)。
? 單元測(cè)試與線上故障沒(méi)有辯證關(guān)系。好的單元測(cè)試能夠最大限度地規(guī)避線上故障。
更多建議: