開(kāi)發(fā)測(cè)試一山容得二虎,30條有關(guān)測(cè)試的故事和事故

軟件工程規(guī)則和測(cè)試積累的最佳實(shí)踐阴颖,能幫助企業(yè)顯著節(jié)省時(shí)間活喊,減少痛點(diǎn)。良好的測(cè)試實(shí)踐既可以確保質(zhì)量標(biāo)準(zhǔn)量愧,也可以指導(dǎo)和塑造每個(gè)程序員的發(fā)展钾菊。

小數(shù)今天推送的這篇文章帅矗,文中的許多原則都與測(cè)試實(shí)踐和理想有關(guān),有一些還是Python特有的煞烫。正如本文作者所說(shuō)浑此,程序員的那些固執(zhí)己見(jiàn),強(qiáng)烈的意見(jiàn)表達(dá)和堅(jiān)持滞详,往往是激情的最好表現(xiàn)凛俱。

  1. YAGNI:不要編寫(xiě)現(xiàn)在尚不需要,而將來(lái)可能需要的代碼×霞ⅲ現(xiàn)在的代碼不可避免地會(huì)變成死代碼或需要重寫(xiě)蒲犬,因?yàn)槲磥?lái)的用例總是與設(shè)想的不同。如果把代碼放在未來(lái)的用例中岸啡,在代碼審查中要提出質(zhì)疑暖哨。(例如,可以并且必須設(shè)計(jì)API來(lái)允許將來(lái)的用例凰狞,不過(guò),這是另外一個(gè)問(wèn)題沛慢。)

注解代碼也是如此赡若。如果一個(gè)注釋代碼塊進(jìn)入發(fā)行版,它就不應(yīng)該存在团甲。如果是可以恢復(fù)的代碼逾冬,創(chuàng)建一個(gè)ticket,并引用代碼刪除的提交散列躺苦。YAGNI 是敏捷編程的核心元素身腻。Kent Beck提供的極限編程解釋(Extreme Programming Explained)就是最好的參考。

2.測(cè)試本身不需要測(cè)試匹厘。用于測(cè)試的基礎(chǔ)架構(gòu)嘀趟,框架和庫(kù)需要測(cè)試。除非確實(shí)需要愈诚,通常不要測(cè)試瀏覽器或外部庫(kù)她按。測(cè)試你寫(xiě)的代碼,而并非其他人的炕柔。

3.第三次編寫(xiě)相同代碼時(shí)酌泰,是將其抽取到通用幫助器(并為其編寫(xiě)測(cè)試)的正確時(shí)機(jī)。測(cè)試中的輔助功能不需要測(cè)試; 當(dāng)把它們分解出來(lái)并進(jìn)行重用時(shí)匕累,才需要測(cè)試陵刹。到第三次編寫(xiě)類似的代碼時(shí),會(huì)清楚地知道正在解決什么樣的問(wèn)題欢嘿。

4.涉及到API設(shè)計(jì):簡(jiǎn)單的事情簡(jiǎn)單化; 復(fù)雜的事情可能如果可能也簡(jiǎn)單化衰琐。首先設(shè)計(jì)一個(gè)簡(jiǎn)單的情況也糊,如果可能,最好使用零配置或參數(shù)化碘耳。為更復(fù)雜和更靈活的用例添加選項(xiàng)或其他API方法显设。

5.快速失敗。盡可能早地檢查輸入辛辨,并在無(wú)意義的輸入或無(wú)效狀態(tài)上失敗捕捂,使用異常或錯(cuò)誤響應(yīng)斗搞,來(lái)確定問(wèn)題指攒。允許代碼“創(chuàng)新”,也就是說(shuō)僻焚,通常情況下允悦,不要對(duì)輸入驗(yàn)證進(jìn)行類型檢查。

  1. 單元測(cè)試是對(duì)行為單元的測(cè)試虑啤,而不是對(duì)實(shí)現(xiàn)單元隙弛。改變實(shí)現(xiàn),而不是改變行為或被迫改變?nèi)魏螠y(cè)試狞山,當(dāng)然這點(diǎn)并不是總能實(shí)現(xiàn)全闷。在可能的情況下,將測(cè)試對(duì)象視為黑盒子萍启,通過(guò)公共 API 進(jìn)行測(cè)試总珠,而無(wú)需調(diào)用私有方法或修改狀態(tài)。

對(duì)于一些復(fù)雜的場(chǎng)景勘纯,比如一些特定復(fù)雜狀態(tài)下局服,測(cè)試行為找到一個(gè)難以理解的錯(cuò)誤。編寫(xiě)測(cè)試確實(shí)有助于解決這個(gè)問(wèn)題驳遵,因?yàn)樗鼤?huì)迫使你在編寫(xiě)代碼之前淫奔,考慮清楚代碼的行為以及如何測(cè)試。測(cè)試首先鼓勵(lì)更小超埋,更模塊化的代碼單元搏讶。

7.對(duì)于單元測(cè)試(包括測(cè)試基礎(chǔ)結(jié)構(gòu)測(cè)試),應(yīng)該測(cè)試所有的代碼路徑霍殴。100%的覆蓋率是一個(gè)很好的起點(diǎn)媒惕。你不能涵蓋所有可能的排列/組合狀態(tài)。在有很好的理由時(shí)来庭,代碼路徑才能被測(cè)試妒蔚。缺少時(shí)間不是一個(gè)好的理由,這往往導(dǎo)致最終花費(fèi)更多時(shí)間。好的理由包括:真正無(wú)法測(cè)試肴盏,在實(shí)踐中不可能實(shí)現(xiàn)科盛,或者在測(cè)試中其他地方被覆蓋。沒(méi)有測(cè)試的代碼要承擔(dān)責(zé)任菜皂。衡量覆蓋率贞绵,并拒絕降低覆蓋率的百分比是朝正確方向前進(jìn)的一種方法。

8.代碼是敵人:可能出錯(cuò)恍飘,需要維護(hù)榨崩。少寫(xiě)代碼。刪除代碼章母。不要編寫(xiě)你不需要的代碼母蛛。

9.隨著時(shí)間的推移,代碼注釋不可避免地成為謊言乳怎。實(shí)際上彩郊,很少有人在事情發(fā)生變化時(shí)更新評(píng)論。通過(guò)良好的命名實(shí)踐和已知的編程風(fēng)格蚪缀,努力使代碼有可讀性和自我記錄秫逝。

不明確的代碼確實(shí)需要注釋,比如圍繞一個(gè)模糊的錯(cuò)誤或不可能的條件询枚,或者必要的優(yōu)化筷登。

10.防守地寫(xiě)。要總是想可能出現(xiàn)什么問(wèn)題哩盲,無(wú)效輸入會(huì)發(fā)生什么,什么可能導(dǎo)致失敗狈醉,這有助于在錯(cuò)誤發(fā)生前發(fā)現(xiàn)錯(cuò)誤廉油。

11.如果邏輯無(wú)狀態(tài)且無(wú)副作用,則易于進(jìn)行單元測(cè)試苗傅。將邏輯分解成獨(dú)立的函數(shù)抒线,而不是混合成有狀態(tài)和副作用的代碼。將有狀態(tài)和帶副作用的代碼分離成更小的函數(shù)渣慕,可以更容易地模擬和單元測(cè)試嘶炭。副作用確實(shí)需要測(cè)試,測(cè)試一次并在其他地方進(jìn)行模擬逊桦,是比較好的做法眨猎。

12.Globals are bad。功能優(yōu)于類型强经,對(duì)象比復(fù)雜的數(shù)據(jù)結(jié)構(gòu)更好睡陪。

13.使用 Python 內(nèi)置類型和方法比編寫(xiě)自己的類型更快(除非用C編寫(xiě))。如果考慮性能,嘗試解決如何使用標(biāo)準(zhǔn)內(nèi)置類型而不是自定義對(duì)象兰迫。

  1. 依賴注入是一種有用的編程模式信殊,可以清楚了解依賴關(guān)系。(讓對(duì)象汁果,方法等接收依賴關(guān)系作為參數(shù)涡拘,而不是自己實(shí)例化新的對(duì)象。)這是一種交換据德,使API簽名更加復(fù)雜鳄乏。如果完成依賴項(xiàng)需要使用10個(gè)參數(shù),說(shuō)明代碼太多了晋控。

  2. 越需要模擬測(cè)試代碼汞窗,它就會(huì)越糟糕。需要實(shí)例化和放置的代碼越多赡译,用來(lái)測(cè)試特定的行為仲吏,代碼就越糟糕。測(cè)試的目標(biāo)是小型可測(cè)試單元蝌焚,和更高級(jí)別的集成和功能測(cè)試裹唆,來(lái)測(cè)試這些單元是否正確地協(xié)作。

16.面向外部的 API 是要“預(yù)先設(shè)計(jì)”的只洒,它關(guān)系到未來(lái)用例许帐。改變 API 對(duì)自己和用戶來(lái)說(shuō)都是一種痛苦,而創(chuàng)造向后兼容性是非潮锨矗可怕的成畦,盡管有時(shí)不可避免。精心設(shè)計(jì)面向外部的API涝开,仍然堅(jiān)持“簡(jiǎn)單的事情簡(jiǎn)單化”的原則循帐。

17.如果一個(gè)函數(shù)或方法超過(guò)30行代碼,就要考慮分解舀武。好的最大模塊大小約為500線拄养。測(cè)試文件往往比這個(gè)更長(zhǎng)。

18.不要在難以測(cè)試的對(duì)象構(gòu)造函數(shù)中工作银舱。不要把代碼放在init.py中瘪匿。程序員不希望在init.py找到代碼。

  1. DRY(Don’t Repeat Yourself不要重復(fù)自己)在測(cè)試中比在生產(chǎn)中重要得多寻馏。單個(gè)測(cè)試文件的可讀性比可維護(hù)性更重要(突破可重用的塊)棋弥。這是因?yàn)闇y(cè)試是單獨(dú)執(zhí)行和讀取的,而不是作為大系統(tǒng)的一部分诚欠。過(guò)多的重復(fù)意味著可重用的組件可以方便地創(chuàng)建嘁锯,但是與生產(chǎn)相比宪祥,測(cè)試的重要性低得多。

20.當(dāng)看到需要并有機(jī)會(huì)時(shí)進(jìn)行重構(gòu)家乘。編程是關(guān)于抽象的蝗羊,抽象映射越接近問(wèn)題域,代碼就越容易理解和維護(hù)仁锯。隨著系統(tǒng)有機(jī)地增長(zhǎng)耀找,需要為擴(kuò)展用例而改變結(jié)構(gòu)。系統(tǒng)超出抽象和結(jié)構(gòu)业崖,而不改變它們成為技術(shù)債務(wù)野芒,這會(huì)更痛苦,更緩慢双炕,更多bug狞悲。包括重構(gòu)成本,包括對(duì)功能的預(yù)估妇斤。你把債務(wù)拖得越久摇锋,它積累的利息就越高。Michael Feathers 撰寫(xiě)了一本關(guān)于重構(gòu)和測(cè)試的書(shū)籍站超,其中著重介紹了遺留代碼荸恕。

21.正確的編寫(xiě)代碼第一,速度第二死相。處理性能問(wèn)題時(shí)融求,請(qǐng)務(wù)必在修復(fù)之前進(jìn)行配置。瓶頸通常出乎你的意料算撮。編寫(xiě)難懂的代碼如果是為了速度更快生宛,為此你進(jìn)行了配置并證明這么做是值得的,那么也僅僅是速度上值得而已肮柜。編寫(xiě)一個(gè)測(cè)試茅糜,訓(xùn)練正在配置的代碼,讓它知道什么情況下會(huì)變得更簡(jiǎn)單素挽,并且留在測(cè)試套件中,來(lái)防止性能下降狸驳。(通常情況下预明,添加計(jì)時(shí)代碼總是會(huì)改變代碼的性能特點(diǎn),使性能變得經(jīng)常差強(qiáng)人意耙箍。)

22.更小范圍的單元測(cè)試在失敗時(shí)會(huì)提供更有價(jià)值的信息撰糠。要判定錯(cuò)誤,有一半的系統(tǒng)測(cè)試行為的測(cè)試需要依據(jù)更多的調(diào)查辩昆。一般來(lái)說(shuō)阅酪,運(yùn)行時(shí)間超過(guò)0.1秒的測(cè)試不是單元測(cè)試。沒(méi)有所謂的慢單元測(cè)試。通過(guò)嚴(yán)格范圍的單元測(cè)試測(cè)試行為术辐,你的測(cè)試可以作為代碼實(shí)際規(guī)范砚尽。理想情況下,如果有人想了解你的代碼辉词,應(yīng)該能夠?qū)y(cè)試套件作為行為的“文檔”必孤。

  1. “這里沒(méi)有發(fā)明”并不像人們所說(shuō)的那么糟糕。如果我們編寫(xiě)代碼瑞躺,我們知道它的作用敷搪,知道如何維護(hù)它,可以自由地?cái)U(kuò)展和修改它幢哨。這是遵循了YAGNI的原則:我們有需要用例的特定代碼赡勘,而并非通用代碼,通用代碼會(huì)給我們不需要的部分帶來(lái)復(fù)雜性捞镰。另一方面闸与,代碼是敵人,擁有更多的代碼沒(méi)有好處曼振,當(dāng)引入新的依賴關(guān)系時(shí)需要考慮權(quán)衡几迄。

24.共享代碼所有權(quán)是目標(biāo)。孤立的知識(shí)沒(méi)什么好冰评,這意味著至少要討論映胁、記錄貫徹設(shè)計(jì)決策和實(shí)施決策。代碼審查時(shí)開(kāi)始討論設(shè)計(jì)決策是最糟糕甲雅,因?yàn)樵诰帉?xiě)代碼之后進(jìn)行徹底的更改太難克服了解孙。當(dāng)然,在Review時(shí)指出和修改設(shè)計(jì)錯(cuò)誤抛人,比永遠(yuǎn)不總結(jié)不思考要好得多弛姜。

  1. Generators rock! 與有狀態(tài)的對(duì)象相比,它們用于迭代或重復(fù)執(zhí)行通常更短妖枚,更容易理解廷臼。

26.讓我們成為工程師!設(shè)計(jì)绝页、建立強(qiáng)大和良好實(shí)施的系統(tǒng)荠商,而不是增加有機(jī)怪物。編程是一個(gè)平衡的行為续誉,我們并不總是建造火箭飛船莱没,過(guò)度設(shè)計(jì)(onion architecture洋蔥架構(gòu))與設(shè)計(jì)不足的代碼同樣令人痛苦。羅伯特?馬丁(Robert Martin)所做的幾乎任何事情都值得一讀酷鸦,“ 干凈架構(gòu):軟件結(jié)構(gòu)和設(shè)計(jì)指南”( Clean Architecture: A Craftsman’s Guide to Software Structure and Design )是這方面的好資源饰躲。設(shè)計(jì)模式( Design Patterns)是每個(gè)工程師應(yīng)該閱讀的經(jīng)典編程書(shū)籍牙咏。

27.間歇性地失敗的測(cè)試會(huì)侵蝕測(cè)試套件的價(jià)值,以至于最終每個(gè)人都忽略測(cè)試運(yùn)行的結(jié)果嘹裂。修復(fù)或刪除間歇性失敗的測(cè)試是痛苦的妄壶,但值得努力。

28.一般來(lái)說(shuō)焦蘑,尤其是在測(cè)試中盯拱,等待一個(gè)具體的改變,而不是任意時(shí)間內(nèi)sleeping例嘱。Voodoo sleeps 很難理解狡逢,而且會(huì)放慢測(cè)試套件。

29.至少要看到你的測(cè)試失敗過(guò)一次拼卵。將一個(gè)蓄意的 bug 放入讓它失敗奢浑,或在測(cè)試行為完成之前運(yùn)行測(cè)試。否則腋腮,你不知道你真的在測(cè)試雀彼。偶爾寫(xiě)寫(xiě)測(cè)試代碼實(shí)際并不測(cè)試任何東西,或?qū)懹肋h(yuǎn)不會(huì)失敗的測(cè)試即寡,都是很容易的徊哑。

30.最后,管理要點(diǎn):持續(xù)的功能研發(fā)是開(kāi)發(fā)軟件的一個(gè)可怕方法聪富。不讓開(kāi)發(fā)人員在工作感到驕傲, 就不會(huì)從中獲得最大的利益莺丑。不解決技術(shù)債務(wù),會(huì)拖慢開(kāi)發(fā)速度墩蔓,并導(dǎo)致更糟糕的梢莽、更多bug的產(chǎn)品。

原文作者:Michael Foord
原文鏈接:
https://opensource.com/article/17/5/30-best-practices-software-development-and-testing

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末奸披,一起剝皮案震驚了整個(gè)濱河市昏名,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌阵面,老刑警劉巖轻局,帶你破解...
    沈念sama閱讀 222,729評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異样刷,居然都是意外死亡仑扑,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,226評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)颂斜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人拾枣,你說(shuō)我怎么就攤上這事沃疮『腥茫” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,461評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵司蔬,是天一觀的道長(zhǎng)邑茄。 經(jīng)常有香客問(wèn)我,道長(zhǎng)俊啼,這世上最難降的妖魔是什么肺缕? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,135評(píng)論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮授帕,結(jié)果婚禮上同木,老公的妹妹穿的比我還像新娘。我一直安慰自己跛十,他們只是感情好彤路,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,130評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著芥映,像睡著了一般洲尊。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上奈偏,一...
    開(kāi)封第一講書(shū)人閱讀 52,736評(píng)論 1 312
  • 那天坞嘀,我揣著相機(jī)與錄音,去河邊找鬼惊来。 笑死丽涩,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的唁盏。 我是一名探鬼主播内狸,決...
    沈念sama閱讀 41,179評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼厘擂!你這毒婦竟也來(lái)了昆淡?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 40,124評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤刽严,失蹤者是張志新(化名)和其女友劉穎昂灵,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體舞萄,經(jīng)...
    沈念sama閱讀 46,657評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡眨补,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,723評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了倒脓。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片撑螺。...
    茶點(diǎn)故事閱讀 40,872評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖崎弃,靈堂內(nèi)的尸體忽然破棺而出甘晤,到底是詐尸還是另有隱情含潘,我是刑警寧澤,帶...
    沈念sama閱讀 36,533評(píng)論 5 351
  • 正文 年R本政府宣布线婚,位于F島的核電站遏弱,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏塞弊。R本人自食惡果不足惜漱逸,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,213評(píng)論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望游沿。 院中可真熱鬧饰抒,春花似錦、人聲如沸奏候。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,700評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)蔗草。三九已至咒彤,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間咒精,已是汗流浹背镶柱。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,819評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留模叙,地道東北人歇拆。 一個(gè)月前我還...
    沈念sama閱讀 49,304評(píng)論 3 379
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像范咨,于是被迫代替她去往敵國(guó)和親故觅。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,876評(píng)論 2 361

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

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,332評(píng)論 25 707
  • 黑盒測(cè)試案例設(shè)計(jì)技術(shù)篇 1 概述 本章介紹黑盒測(cè)試的概念和進(jìn)行黑盒測(cè)試的目的與意義,及關(guān)于等價(jià)類劃分替蛉、邊界值分析贯溅、...
    西邊人閱讀 16,951評(píng)論 0 41
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)躲查,斷路器它浅,智...
    卡卡羅2017閱讀 134,716評(píng)論 18 139
  • 名家書(shū)錄之三十六(2017.12.20) 【什么是靈魂】 正直、真誠(chéng)镣煮、洞察力姐霍、分辨力、閱歷、勇敢的心镊折、目光的犀利黔衡、...
    永遠(yuǎn)的浩子閱讀 280評(píng)論 1 1
  • 一:人格 我們這個(gè)時(shí)代是一個(gè)知識(shí)高速更新、不斷迭代的一個(gè)時(shí)代腌乡,每一個(gè)愛(ài)學(xué)習(xí)、求進(jìn)步的人都會(huì)面臨知識(shí)焦慮的問(wèn)題...
    朱炫羽閱讀 381評(píng)論 0 0