免費(fèi)午餐——先寫單元測(cè)試

字號(hào):

前些天看見(jiàn)有朋友的MSN簽名檔寫著“unit testing”,就問(wèn)了一下他們的單元測(cè)試是怎么做的??磥?lái)他們沒(méi)有真正做起來(lái),只是小范圍的試一試。
    一方面,他們沒(méi)有cruise control之類的工具,甚至連daily build都不見(jiàn)得有,單元測(cè)試也不上傳到版本控制里。這樣做測(cè)試的意義就不大了。
    另一方面,他好像把單元測(cè)試和接收測(cè)試(acceptance testing)、集成測(cè)試(integration testing)搞混淆了。因?yàn)樗f(shuō),業(yè)務(wù)邏輯很復(fù)雜,測(cè)試數(shù)據(jù)不好做……
    單元測(cè)試,顧名思義,就是對(duì)一個(gè)單元的測(cè)試(好像什么也沒(méi)說(shuō))。通常這個(gè)單元是指(類的成員)函數(shù),或者函數(shù)的一個(gè)功能。
    每個(gè)測(cè)試就只針對(duì)一點(diǎn),不涉及其余,還是比較好寫的。函數(shù)的輸入是什么,(對(duì)象當(dāng)時(shí)的狀態(tài)是什么),得到的輸出是什么;有幾種不同的情況……
    我感覺(jué),同一個(gè)函數(shù)的單元測(cè)試加在一起,就相當(dāng)于這個(gè)函數(shù)的詳細(xì)設(shè)計(jì)文檔。自然,設(shè)計(jì)文檔應(yīng)該在實(shí)現(xiàn)之前寫,而不是實(shí)現(xiàn)了以后再補(bǔ)。
    和傳統(tǒng)開(kāi)發(fā)方法里的詳細(xì)設(shè)計(jì)不同,寫一個(gè)單元測(cè)試,就寫一段代碼讓它通過(guò)。這樣你就不需要在實(shí)現(xiàn)的時(shí)候,再去讀文檔,再去回憶當(dāng)時(shí)是怎么想的,能提高效率;更重要的是,這個(gè)“文檔”是能反復(fù)運(yùn)行的,可以保證和實(shí)現(xiàn)的一致性。
    如果你的開(kāi)發(fā)環(huán)境配置的好,照我的經(jīng)驗(yàn),寫單元測(cè)試再寫代碼,和直接寫代碼相比,不會(huì)多花什么時(shí)間。
    編碼過(guò)程中有相當(dāng)一部分時(shí)間是花在想清楚下一步要做什么上,想到了就把它寫成一個(gè)測(cè)試。這么做是要花一點(diǎn)點(diǎn)時(shí)間,不過(guò)能幫你盡快驗(yàn)證下面的實(shí)現(xiàn)跟你現(xiàn)在想的一致;能幫你理清思路,到底有幾種情況需要考慮,就寫幾個(gè)測(cè)試;能讓函數(shù)的功能更明確,只有功能明確,才能明確的測(cè)試;能讓你的接口更合理,因?yàn)椴缓侠淼脑?,依賴關(guān)系太多或者接口太復(fù)雜,測(cè)試寫起來(lái)會(huì)很麻煩……
    最重要的是,以后你改了什么東西,破壞了現(xiàn)在的接口,可以馬上知道。不會(huì)在發(fā)版本的最后一天,才有人告訴你:“這個(gè)功能以前是好的,我們已經(jīng)好幾天沒(méi)有重新測(cè)試了?,F(xiàn)在壞了,不知道問(wèn)題在哪里。全體加班吧!”
    不花什么時(shí)間,還有不少好處。免費(fèi)午餐,為什么不試試呢?