讓我們一起聊聊單元測(cè)試的恩怨
單元測(cè)試是一個(gè)偉大的發(fā)明,同時(shí)也是一個(gè)操蛋的發(fā)明。只要團(tuán)隊(duì)碰它,幾乎很難全身而退。
如果是我們自己寫(xiě)的代碼,那么,寫(xiě)寫(xiě)單元測(cè)試也無(wú)傷大雅。但我們絕大多數(shù)人,都是跟在別人后面打掃狗屎,或者是留給別人一堆狗屎。這時(shí)候,單元測(cè)試寫(xiě)起來(lái),就有一種不情不愿的味道。
沒(méi)錯(cuò),就是不想寫(xiě)!
為了應(yīng)付所謂的指標(biāo),我們要給那些遺留代碼,將要發(fā)臭的代碼上一劑良藥:那就是自動(dòng)化。假如這些糟心的代碼,大部分交給機(jī)器去寫(xiě),我想很多人是非常樂(lè)意的。
squaretest
有很多這樣的工具,比如IDEA自帶的。但是它只能生成一些表面功夫的東西,也就是生成一個(gè)骨架而已。

說(shuō)實(shí)話(huà),并沒(méi)有什么鳥(niǎo)用。根本就沒(méi)減少我多少的工作量,該覆蓋不到的代碼,還是覆蓋不到。
這個(gè)時(shí)候,我們需要更高級(jí)一點(diǎn)的工具。經(jīng)過(guò)測(cè)試,現(xiàn)在瞄準(zhǔn)了squaretest。
在IDEA的插件安裝界面中,找到squaretest并安裝之,你就會(huì)擁有這個(gè)功能。

重啟IDEA之后,從你的屎山中,找到最臭的那一塊,然后就可以在菜單中找到這個(gè)工具,生成代碼。
中間的話(huà),可能會(huì)讓你選擇一下語(yǔ)言,選擇一下模版之類(lèi)的,這對(duì)于一個(gè)搞軟件的來(lái)說(shuō)并不是難事,所以這里也不再啰嗦。

好家伙,足足給我生成了上萬(wàn)行的test代碼。這時(shí)候,無(wú)論是交給QA看,還是交給分析工具去玩,都能閃瞎它們的狗眼。
hehehehehehe....漂亮!
報(bào)錯(cuò)不少,還得微調(diào)一下參數(shù)。但大多數(shù)代碼已經(jīng)生成好了,已經(jīng)節(jié)約了很大的力氣了。

其他工具
這貌似不是一個(gè)好的賽道。因?yàn)楹芏喙ぞ叨疾辉趺淳S護(hù)了,或者不怎么好用。用愛(ài)發(fā)電越來(lái)越行不通了。
比如JUnitGenerator2.0,連JUnit5都不支持;AgitarOne,雖然只有30天的試用期,但主頁(yè)也和上古怪獸一樣;Randoop的使用,根本就不是為人類(lèi)設(shè)計(jì)的;Analytix被google收購(gòu)后,幾乎進(jìn)入了墳?zāi)埂?/p>
squaretest,可以說(shuō)是非常好用了。
你需要單元測(cè)試么?
很多人沒(méi)得選,因?yàn)檫@是硬指標(biāo)。如果你的工作流程有問(wèn)題,單元測(cè)試不但不能增彩,反而會(huì)成為累贅。
大多數(shù)情況下,單元測(cè)試不會(huì)減少bug,它們會(huì)根據(jù)bug進(jìn)行調(diào)整,以適應(yīng)正常代碼;另外,如果你的代碼都是一些簡(jiǎn)單的CRUD,寫(xiě)單元測(cè)試看不到任何有益的地方。
這個(gè)現(xiàn)狀,還是要從根源上找原因。
中國(guó)式需求,變化奇快,臨時(shí)需求多,要求快速交付。這些功能,往往復(fù)雜性比較低,編寫(xiě)的代碼并不會(huì)產(chǎn)生過(guò)多的bug;由于變化快,編寫(xiě)的單元測(cè)試也沒(méi)有通用的可能性;一次性的代碼,寫(xiě)完之后可能永遠(yuǎn)不再修改,被扔在一個(gè)遺忘的角落。
要寫(xiě)單元測(cè)試,你要確保你的單元測(cè)試多年之后還可以用。而不是等到項(xiàng)目尾聲,為了達(dá)到指標(biāo)而集中補(bǔ)充單元測(cè)試。單元測(cè)試要想發(fā)揮它的價(jià)值,需要在一開(kāi)始就創(chuàng)建相關(guān)的代碼,捫心自問(wèn),很多團(tuán)隊(duì)是做不到這一點(diǎn)的。
做不到,就不要裝。
單元測(cè)試并不簡(jiǎn)單
有意思的是,即使環(huán)境達(dá)到了要求,所有的接口都提前設(shè)計(jì)了,且保持較少的變動(dòng),我們依然無(wú)法推行單元測(cè)試。
單元測(cè)試從來(lái)不是因?yàn)閷?xiě)單元測(cè)試有多困難,而是大多數(shù)代碼,是無(wú)法寫(xiě)出好的單元測(cè)試的。
在TDD(Test-Driven Development,測(cè)試驅(qū)動(dòng)開(kāi)發(fā))模式下,測(cè)試的動(dòng)作比開(kāi)發(fā)早,屬于預(yù)先設(shè)計(jì)接口定義的范疇。如果你在后期對(duì)接口進(jìn)行了較多的變更,這種方式同樣會(huì)讓開(kāi)發(fā)人員變的痛苦不堪。
單元測(cè)試需要配合極限編程,經(jīng)常對(duì)代碼進(jìn)行重構(gòu)。這是設(shè)計(jì)腐化之后的一種補(bǔ)救式措施。但很多情況下,大家都害怕、拒絕對(duì)舊代碼進(jìn)行修改。工期和穩(wěn)定性是常見(jiàn)的借口,這些借口看起來(lái)比擴(kuò)展性和可測(cè)試性看起來(lái)更正常一些,也更能說(shuō)服高層進(jìn)行決策。
沒(méi)有幾個(gè)技術(shù)決策者,能夠在銷(xiāo)售、產(chǎn)品、老板的重重壓力下保持初心,做這種長(zhǎng)遠(yuǎn)性的規(guī)劃。所以說(shuō)單元測(cè)試肯定是有用的,但卻缺乏實(shí)施的土壤。按時(shí)上線、提前上線、bug數(shù)量,這些常見(jiàn)的指標(biāo),只反映了結(jié)果,那些去改進(jìn)這些結(jié)果的措施,短期效應(yīng)不是很明顯的話(huà),很容易就胎死腹中。
單元測(cè)試還阻礙開(kāi)發(fā)人員重構(gòu)的動(dòng)力。因?yàn)橹貥?gòu)意味著要?jiǎng)雍芏嗟臏y(cè)試代碼,往往很多人偷偷一評(píng)估,就放棄了。
堅(jiān)持對(duì)的事情
選擇一個(gè)優(yōu)秀的團(tuán)隊(duì),是非常重要的。大家都很專(zhuān)業(yè),不會(huì)虧待你所信仰的正確。專(zhuān)業(yè)的人才在二流子團(tuán)隊(duì)中,會(huì)像一個(gè)小丑一樣無(wú)助,大多數(shù)習(xí)以為常的經(jīng)驗(yàn),幾乎無(wú)法實(shí)施。
讓人欣慰的是,追求原則的團(tuán)隊(duì)還是有的,正確的方式可以避免很多曲折的路線,拋掉技術(shù)債所造成的負(fù)面影響。能夠加入這些團(tuán)隊(duì),是非常幸福的事情。
作為程序員,應(yīng)該時(shí)刻保持這種好的習(xí)慣,不要因?yàn)橼s工,忽略了代碼的重構(gòu)和測(cè)試。這些是一個(gè)專(zhuān)業(yè)的技術(shù)人員應(yīng)有的素質(zhì),而不是寄希望于公司的大環(huán)境中。這些好的習(xí)慣,就像人的氣質(zhì)一樣讓人著迷,最終會(huì)讓你超脫于其他人而受益。
作為技術(shù)管理者,你要正確評(píng)估自己的公司環(huán)境,是不是具有單元測(cè)試的生長(zhǎng)土壤。即使你明白單元測(cè)試是有益的,你也不得不做一些取舍。尤其是你判斷項(xiàng)目只不過(guò)是你的墊腳石,3年之后肯定不會(huì)在自己的手里,你更會(huì)任由它自我腐爛掉。如此情況,大家都心知肚明,沒(méi)人會(huì)對(duì)你說(shuō)三道四。
作為非技術(shù)管理人員,當(dāng)有人為你提出類(lèi)似這種耗費(fèi)工期的,長(zhǎng)遠(yuǎn)有益的建議,不要著急否定??匆豢雌渌麅?yōu)秀的企業(yè),是不是也曾因這些短暫的原地踏步而受益過(guò)。無(wú)知并不可怕,可怕的是不相信專(zhuān)業(yè)。如果你肯定了,給予支持,而不要半途而廢。有意思的是,半途而廢最終并不會(huì)廢止,它同樣會(huì)蛻變?yōu)樾问街髁x,將一件美好的事情硬生生變成指標(biāo)。
End
單元測(cè)試代碼是無(wú)聊的、枯燥的,尤其是為別人寫(xiě)的代碼補(bǔ)充單元測(cè)試。通常情況下,如果不發(fā)生bug,沒(méi)有人會(huì)閑的蛋疼去動(dòng)那一堆堆的屎山,除非是不自量力的小牛犢。
這個(gè)時(shí)候,一個(gè)得心應(yīng)手的工具,自動(dòng)幫你完成這些操蛋的工作,讓你的單元測(cè)試代碼擁有和屎山一樣的生命周期,不得不說(shuō)是一件快事。
作者簡(jiǎn)介:小姐姐味道 (xjjdog),一個(gè)不允許程序員走彎路的公眾號(hào)。聚焦基礎(chǔ)架構(gòu)和Linux。十年架構(gòu),日百億流量,與你探討高并發(fā)世界,給你不一樣的味道。我的個(gè)人微信xjjdog0,歡迎添加好友,進(jìn)一步交流。















 
 
 











 
 
 
 