Best practices of Unit test 單元測(cè)試的最佳實(shí)踐, 2023-01-31

(2023.01.31 Tues)

Unit test related

unit test和integration test的區(qū)別

(2023.02.02 Thur)
unit test和integration test的區(qū)別在于隔離程度(level of isolation)亭罪。Unit test必須完全隔離,而integration test在執(zhí)行過程中不能擺脫對(duì)外部依賴理朋。Integration test通常以整合的方式測(cè)試多個(gè)模塊厚掷,因此有了integration test這個(gè)名字。Integration test比unit test提供英勇的更多高級(jí)視角爬凑,因此其提供的反饋更真實(shí)而較少聚焦在某一單一功能徙缴。因?yàn)閕ntegration test對(duì)外部的依賴,可能導(dǎo)致效率變低并難于設(shè)置(setup)嘁信。

Best Practices

(2023.01.31 Tues)

每次只測(cè)一個(gè)功能 Test one thing at a time

比如測(cè)試一個(gè)函數(shù)于样,該函數(shù)返回兩個(gè)數(shù)的和。顯然可以調(diào)用任意兩個(gè)數(shù)字的組合并檢驗(yàn)結(jié)果是否正確來(lái)確認(rèn)函數(shù)是否正確潘靖,盡管這個(gè)方法有若干問題穿剖。

更好的方式是對(duì)函數(shù)的不同部分使用獨(dú)立的測(cè)試。比如可以檢測(cè)該函數(shù)能否正確計(jì)算兩個(gè)正數(shù)的和卦溢,另一個(gè)測(cè)試檢測(cè)能否計(jì)算兩個(gè)負(fù)數(shù)的和糊余,等等秀又。這種獨(dú)立的測(cè)試,其優(yōu)勢(shì)在于贬芥,1) 易于設(shè)計(jì)和維護(hù)吐辙,每次只需要關(guān)注一件事,2) 更精確蘸劈,容錯(cuò)的機(jī)會(huì)少昏苏,3) 易于debug,如果test失敗威沫,很容易知道哪個(gè)部分出錯(cuò)了贤惯。

總之,每次測(cè)試一個(gè)功能會(huì)給unit test帶來(lái)更高效率棒掠,更快更準(zhǔn)確救巷,更易于debug。

起個(gè)有意義的名字 Name tests meanfully

比如測(cè)試頁(yè)面的login功能句柠,用一個(gè)test_login方法來(lái)執(zhí)行浦译。一旦test fails,則無(wú)法知道是因?yàn)槭裁炊鴏ogin失敗溯职。但如果將test_login功能拆分為多個(gè)不同的模塊精盅,比如test_login_with_incorrect_usernametest_login_with_incorrect_password谜酒,等等方法叹俏,則不同的測(cè)試方法失敗可以帶給QA精確的信息,關(guān)于哪里出現(xiàn)了錯(cuò)誤僻族。

除此之外粘驰,有意義的名字對(duì)于非開發(fā)者來(lái)說也友好,見名知其含義述么。

保證單元測(cè)試簡(jiǎn)短而精煉 Keep unit test short and focused

如果unit test過長(zhǎng)蝌数,則很可能測(cè)試超過一件事,將導(dǎo)致測(cè)試難于理解和維護(hù)度秘,同時(shí)也增加測(cè)試過程出問題的機(jī)會(huì)。

如果unit test過于簡(jiǎn)短精煉唆貌,則不會(huì)覆蓋特別多的內(nèi)容,可能會(huì)導(dǎo)致不同的test suite之間有疏漏粱侣。

最好的方案是在簡(jiǎn)短和精煉之間取得一個(gè)平衡油猫,使得測(cè)試易于理解維護(hù)睬关,同時(shí)提供足夠的覆蓋(adequate coverage)电爹。

用斷言驗(yàn)證結(jié)果 Use assertions to validate results

Python unit test中的assertion是一個(gè)基礎(chǔ)部分恤煞,用于判斷代碼中某個(gè)特定不是本該返回怎樣的結(jié)果概漱。如果斷言失敗,則代碼中有bug照弥。

盡管不用斷言也可以通過其他方式判斷代碼是否運(yùn)行正確敢会,但assertion命令更加專業(yè)塞俱。

為每個(gè)測(cè)試方法寫文檔 Write docstrings for each test method

測(cè)試方法中的文檔用于解釋該unit test的目的以及如何使用罐旗。失去了文檔則使用者不得不猜測(cè)該unit test的功能粘我,可能會(huì)導(dǎo)致一些意想不到的錯(cuò)誤都弹。

寫文檔時(shí)迫使代碼開發(fā)者不得不思考每個(gè)test case的最終目的氮昧,幫助理清思路。當(dāng)需要修改該方法梧乘,文檔將提醒開發(fā)該測(cè)試方法的意義和目的仁堪,幫助理順?biāo)悸泛头椒ā?/p>

避免重復(fù) Don't Repeat Yourself (DRY)

代碼重復(fù)不僅低效氛什,也可能導(dǎo)致錯(cuò)誤(error-prone)。如果你需要更新不同地方/方法中的相同代碼段枪眉,則很可能在過程中犯錯(cuò)捺檬。

避免重復(fù)代碼,可以使測(cè)試模塊化贸铜,每個(gè)test case覆蓋單獨(dú)的一個(gè)功能堡纬,使得代碼更高效聂受、易于維護(hù)和少錯(cuò)誤。

(Python)用setUptearDown創(chuàng)建和清理fixture Make use setUp and tearDown to create/clean up Fixture

Fixtures是用于作為測(cè)試基準(zhǔn)(baseline)的對(duì)象或數(shù)據(jù)烤镐。通過setUp()方法創(chuàng)建fixtures蛋济,可確保每個(gè)測(cè)試以clean slate形式運(yùn)行。這可以避免因使用前一次測(cè)試數(shù)據(jù)導(dǎo)致的假陽(yáng)性(false positives)

用這兩種方法創(chuàng)建和清理fixture同樣可以保證測(cè)試的DRY炮叶。如果在多個(gè)測(cè)試中創(chuàng)建相同的對(duì)象或數(shù)據(jù)碗旅,則fixture是個(gè)理想的解決方案。通過將這些對(duì)象/數(shù)據(jù)抽象成一個(gè)fixture悴灵,可以在多個(gè)測(cè)試中直接引用,而不用重復(fù)代碼骂蓖。

使用fixtures可以提高測(cè)試的可讀性和可理解性积瞒。直接通過名字引用fixtures,而無(wú)需寫一堆代碼用來(lái)創(chuàng)建對(duì)象或數(shù)據(jù)登下,這使得測(cè)試使用的數(shù)據(jù)更加明確茫孔,也易于修改。

測(cè)試結(jié)束時(shí)被芳,如果之前設(shè)置了fixture缰贝,則需要用tearDown()方法清理資源,否則后續(xù)測(cè)試中隨著未清理的資源漸漲畔濒,測(cè)試將變慢剩晴。setUp()tearDown()應(yīng)成對(duì)出現(xiàn),否則無(wú)法保證每次測(cè)試始于一個(gè)clean slate.

避免不穩(wěn)定測(cè)試 Avoid brittle tests

不穩(wěn)定測(cè)試(brittle test)是隨著被代碼修改而崩潰的測(cè)試代碼侵状。如果測(cè)試過于針對(duì)代碼赞弥,較容易發(fā)生這種情況。

比如要測(cè)試一個(gè)求和函數(shù)趣兄,一個(gè)不穩(wěn)定測(cè)試會(huì)檢測(cè)返回值是否等于特定輸入列表的預(yù)期和绽左。最初這沒什么問題,但是如果函數(shù)內(nèi)部做出改變艇潭,比如用了不同的算法計(jì)算和拼窥,則測(cè)試將確定失效。

更好的方法是寫測(cè)試檢測(cè)函數(shù)對(duì)于一系列不同的輸入返回正確的和蹋凝。如果函數(shù)改變鲁纠,則這個(gè)測(cè)試不容易崩潰。

總之鳍寂,測(cè)試代碼應(yīng)盡可能獨(dú)立于被測(cè)試代碼的具體實(shí)現(xiàn)房交。這樣能保證即便被測(cè)試代碼發(fā)生改變,測(cè)試仍然可以正常運(yùn)行伐割。

經(jīng)常運(yùn)行測(cè)試代碼 Run your test suite regularly

如果被測(cè)試的代碼經(jīng)常修改候味,而測(cè)試代碼不常運(yùn)行刃唤,則很可能測(cè)試代碼逐漸變得低效。

經(jīng)常運(yùn)行測(cè)試代碼可在易于發(fā)現(xiàn)bugs白群。越早發(fā)現(xiàn)越容易解決尚胞。如果被測(cè)試代碼已經(jīng)上線卻未運(yùn)行測(cè)試,則不易追蹤代碼中的問題帜慢。

(2023.02.01 Wed)

測(cè)試應(yīng)保證確定性 Test should be deterministic

確定性指的是在被測(cè)試代碼沒有修改的情況下笼裳,測(cè)試代碼的行為和結(jié)果應(yīng)該總是相同。確定性一定程度上構(gòu)成了測(cè)試的可被信任的程度粱玲。

為保證確定性躬柬,代碼需要完全隔離(completely isolated),測(cè)試不能代碼不能依賴

  • 其他test cases
  • 環(huán)境變量抽减,諸如當(dāng)前時(shí)間允青、系統(tǒng)語(yǔ)言設(shè)定、文件系統(tǒng)卵沉、網(wǎng)絡(luò)颠锉、API等

總之,test case的輸出產(chǎn)生變化史汗,當(dāng)且僅當(dāng)被測(cè)試的代碼發(fā)生變化琼掠。

測(cè)試成為構(gòu)建過程的一部分 Make test a part of build process

考慮到我們討論的是自動(dòng)化測(cè)試,將測(cè)試加入build process就很有意義停撞。確保構(gòu)建過程執(zhí)行unit test并在測(cè)試失敗時(shí)將構(gòu)建標(biāo)記為broken.

盡管對(duì)于開發(fā)者來(lái)說頻繁在開發(fā)機(jī)上運(yùn)行測(cè)試代碼是必要步驟瓷蛙,特別是基于測(cè)試的開發(fā)(TDD),但這仍然不夠戈毒。在構(gòu)建過程中加入unit test使得系統(tǒng)更加安全速挑,比如開發(fā)者在local開發(fā)時(shí)忘記執(zhí)行unit test,CI server不會(huì)忘記副硅。

Reference

1 climbtheladder點(diǎn)com姥宝,10 Python Unit Testing Best Practices
2 testim點(diǎn)io,Unit Testing Best Practices: 9 to Ensure You Do It Right

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末恐疲,一起剝皮案震驚了整個(gè)濱河市撮珠,隨后出現(xiàn)的幾起案子蛮放,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,490評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件您没,死亡現(xiàn)場(chǎng)離奇詭異菌瘪,居然都是意外死亡份殿,警方通過查閱死者的電腦和手機(jī)耸黑,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人笤受,你說我怎么就攤上這事穷缤。” “怎么了箩兽?”我有些...
    開封第一講書人閱讀 165,830評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵津肛,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我汗贫,道長(zhǎng)身坐,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,957評(píng)論 1 295
  • 正文 為了忘掉前任落包,我火速辦了婚禮部蛇,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘咐蝇。我一直安慰自己涯鲁,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評(píng)論 6 393
  • 文/花漫 我一把揭開白布嘹害。 她就那樣靜靜地躺著撮竿,像睡著了一般吮便。 火紅的嫁衣襯著肌膚如雪笔呀。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,754評(píng)論 1 307
  • 那天髓需,我揣著相機(jī)與錄音许师,去河邊找鬼。 笑死僚匆,一個(gè)胖子當(dāng)著我的面吹牛微渠,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播咧擂,決...
    沈念sama閱讀 40,464評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼逞盆,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了松申?” 一聲冷哼從身側(cè)響起云芦,我...
    開封第一講書人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎贸桶,沒想到半個(gè)月后舅逸,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,847評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡皇筛,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評(píng)論 3 338
  • 正文 我和宋清朗相戀三年琉历,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,137評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡旗笔,死狀恐怖彪置,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情换团,我是刑警寧澤悉稠,帶...
    沈念sama閱讀 35,819評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站艘包,受9級(jí)特大地震影響的猛,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜想虎,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評(píng)論 3 331
  • 文/蒙蒙 一卦尊、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧舌厨,春花似錦岂却、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至揉燃,卻和暖如春扫尺,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背炊汤。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工正驻, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人抢腐。 一個(gè)月前我還...
    沈念sama閱讀 48,409評(píng)論 3 373
  • 正文 我出身青樓姑曙,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親迈倍。 傳聞我的和親對(duì)象是個(gè)殘疾皇子伤靠,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • erlang 單元測(cè)試 learn you some erlang for great good 歐盟國(guó)家委員會(huì)...
    蟲大俠閱讀 1,162評(píng)論 0 1
  • 一 :前言 很多的開發(fā)者 都聽說過單元測(cè)試,但是不可否認(rèn) 很多開發(fā)者 在實(shí)際開發(fā)中很少使用這個(gè) 單元測(cè)試啼染。 大部分...
    LikeSomeBody閱讀 36,925評(píng)論 7 101
  • UnitTest單元測(cè)試框架 一宴合、單元測(cè)試 單元測(cè)試概念單元測(cè)試(unit testing),是指對(duì)軟件中的最小可...
    樂智由我閱讀 841評(píng)論 0 1
  • unittest作為單元測(cè)試框架以一個(gè)標(biāo)準(zhǔn)模塊放入python的開發(fā)包中提完,測(cè)試框架可以提供用例的組織與執(zhí)行形纺,提供豐...
    奧利奧_4e9e閱讀 527評(píng)論 0 3
  • 什么是單元測(cè)試 單元測(cè)試是軟件開發(fā)過程中的一種質(zhì)量保證手段。最初的來(lái)源是想模仿對(duì)硬件芯片做單元測(cè)試那樣徒欣,在軟件中也...
    MagicBowen閱讀 22,196評(píng)論 0 18