什么是單元測(cè)試
單元測(cè)試(unit testing),是指對(duì)軟件中的最小可測(cè)試單元進(jìn)行檢查和驗(yàn)證垒在。
單元測(cè)試的作用
保證代碼質(zhì)量,在漫長(zhǎng)的系統(tǒng)維護(hù)過程中保證系統(tǒng)穩(wěn)定性。
單元測(cè)試的好處
通過先測(cè)試最小模塊呈枉,保證最小模塊的質(zhì)量來最大保證系統(tǒng)質(zhì)量趁尼。
為以后的開發(fā)提供支援。就算是開發(fā)后期猖辫,我們也可以輕松的增加功能或更改程序結(jié)構(gòu)酥泞,而不用擔(dān)心這個(gè)過程中會(huì)破壞重要的東西。而且它為代碼的重構(gòu)提供了保障啃憎。
編寫單元測(cè)試將使我們從調(diào)用者觀察芝囤、思考。特別是先寫測(cè)試(Test First)辛萍,迫使我們把程序設(shè)計(jì)成易于調(diào)用和可測(cè)試的悯姊,即迫使我們解除軟件中的耦合。
單元測(cè)試是一種無價(jià)的文檔贩毕,它是展示函數(shù)或類如何使用的最佳文檔悯许。這份文檔是可編譯、可運(yùn)行的耳幢,并且它保持最新岸晦,永遠(yuǎn)與代碼同步。
自動(dòng)化的單元測(cè)試避免了代碼出現(xiàn)回歸睛藻,提交之前就自動(dòng)執(zhí)行測(cè)試启上,那提交上來的代碼就是有正確的。
單元測(cè)試的目標(biāo)
驗(yàn)證“自己寫的一小段代碼是不是符合設(shè)計(jì)邏輯的”店印。這“一小段代碼”冈在,就是所謂的“單元”。
單元測(cè)試應(yīng)該由誰編寫
開發(fā)人員自己按摘。
單元測(cè)試往往從開發(fā)過程中就開始了包券,開發(fā)同學(xué)需要先用單元測(cè)試驗(yàn)過了自己寫的新代碼沒有問題并且老代碼也不會(huì)被影響才能提測(cè),開發(fā)同學(xué)不能將滿是bug的代碼就丟給測(cè)試同學(xué)炫贤。
為什么單元測(cè)試難以落地
對(duì)單元測(cè)試的誤解:
- 單元測(cè)試的目標(biāo)不明確溅固。“壓根就沒搞明白要測(cè)試什么兰珍,保證什么東西是對(duì)的”侍郭。“保證代碼都是正確的”這一句話掠河,就如同“開發(fā)一個(gè)微信”亮元,是一件不可能完成的任務(wù)。
- 對(duì)單元測(cè)試工作量的低估唠摹。為了讓 TestCase 發(fā)揮作用爆捞,讓測(cè)試容易運(yùn)行,可以隔離勾拉,可重復(fù)煮甥,穩(wěn)定的跑盗温,需要學(xué)習(xí)和實(shí)施的東西非常多,甚至不亞于功能開發(fā)本身成肘。低估肌访,尤其是 Leader 對(duì)單元測(cè)試的低估,都可能讓它最后變成“面子工程”艇劫。
- 心態(tài)上抵觸。很多開發(fā)同學(xué)認(rèn)為“測(cè)試就應(yīng)該只讓測(cè)試工程師負(fù)責(zé)的”而排斥這件事惩激。
什么時(shí)候開始單元測(cè)試
隨著不斷的迭代店煞,代碼的組織才能慢慢優(yōu)化和清晰,這些穩(wěn)固的代碼產(chǎn)生的接口风钻、模型才有被測(cè)試保護(hù)的意義顷蟀。
隨著業(yè)務(wù)慢慢穩(wěn)定,團(tuán)隊(duì)人數(shù)和用戶量慢慢多起來后骡技,對(duì)代碼的修改會(huì)陷入巨大的痛苦和不安中鸣个,代碼相關(guān)影響無法控制時(shí),也很自然的需要一點(diǎn)一點(diǎn)的把最重要的布朦、穩(wěn)固的邏輯的測(cè)試補(bǔ)充上囤萤。
參考經(jīng)驗(yàn):
- 一個(gè)項(xiàng)目代碼在不斷迭代大概10個(gè)月后
- 或者團(tuán)隊(duì)技術(shù)人員已經(jīng)超過5個(gè)人
- 或者活躍用戶已經(jīng)超過1萬人
就必須有測(cè)試保護(hù)。如果用動(dòng)態(tài)語言(js是趴,python等)編寫程序涛舍,因?yàn)闆]有編譯器的保護(hù),就更要寫測(cè)試唆途。
單元測(cè)試用例設(shè)計(jì)
任何一個(gè)單元測(cè)試都應(yīng)該包含:
- 正常輸入
- 離散覆蓋參數(shù)值域
- 邊界輸入
- 空值驗(yàn)證
- 零值驗(yàn)證
- 最大值驗(yàn)證
- 非法輸入
- 入?yún)?shù)據(jù)類型非法
- 內(nèi)存溢出驗(yàn)證
單元測(cè)試的驗(yàn)證級(jí)別
網(wǎng)上大鸥谎牛總結(jié)的。這個(gè)問題可以和上面的用例設(shè)計(jì)結(jié)合起來肛搬。
- Level 1:正常流程可用没佑,即一個(gè)函數(shù)在輸入正確的參數(shù)時(shí),會(huì)有正確的輸出
- Level 2:異常流程可拋出邏輯異常温赔,即輸入?yún)?shù)有誤時(shí)蛤奢,不能拋出系統(tǒng)異常,而是用自己定義的邏輯異常通知上層調(diào)用代碼其錯(cuò)誤之處
- Level 3:極端情況和邊界數(shù)據(jù)可用让腹,對(duì)輸入?yún)?shù)的邊界情況也要單獨(dú)測(cè)試远剩,確保輸出是正確有效的
- Level 4:所有分支、循環(huán)的邏輯走通骇窍,不能有任何流程是測(cè)試不到的
- Level 5:輸出數(shù)據(jù)的所有字段驗(yàn)證瓜晤,對(duì)有復(fù)雜數(shù)據(jù)結(jié)構(gòu)的輸出,確保每個(gè)字段都是正確的
根據(jù)自己當(dāng)時(shí)的情況判斷做到哪一個(gè)級(jí)別腹纳。一般做到 Level 2 就已經(jīng)能夠發(fā)現(xiàn)大部分的問題痢掠。
單元測(cè)試的冪等性
對(duì)于單元測(cè)試來說驱犹,保證其冪等性非常重要。
冪等就是在相同輸入的前提下足画,其輸出結(jié)果不隨時(shí)間而改變雄驹。
對(duì)測(cè)試友好的代碼的話,則需要盡可能的寫出各種純函數(shù)淹辞,從而保證冪等性医舆。
應(yīng)該盡量保證除待驗(yàn)證的代碼之外,所有的不純的依賴都要盡量 mock象缀,以實(shí)現(xiàn)測(cè)冪等蔬将。