介紹怎么做單元測(cè)試的書很多,這里主要解答:為什么單元測(cè)試。
客觀來說,單元測(cè)試和使用版本控制系統(tǒng)(GIT,SVN)是一樣重要的。
為什么單元測(cè)試如此重要,但你卻感受不到。首先要知道,代碼的終極目標(biāo)有兩個(gè),第一個(gè)是實(shí)現(xiàn)需求,第二個(gè)是提高代碼質(zhì)量和可維護(hù)性。
單元測(cè)試是為了提高代碼質(zhì)量和可維護(hù)性,是實(shí)現(xiàn)代碼的第二個(gè)目標(biāo)的一種方法。(注:代碼的可維護(hù)性是指增加一個(gè)新功能,或改變現(xiàn)有功能的成本,成本越低,可維護(hù)性即越高。)
01、Hello word
任何一個(gè)偉大的程序員都是從最簡(jiǎn)單的代碼開始寫起的,假設(shè)你的第一個(gè)程序是Hello World,任何一個(gè)語(yǔ)言實(shí)現(xiàn)這個(gè)程序都只需要不到5行代碼。這個(gè)程序需要單元測(cè)試嗎?
我們看看這個(gè)程序是否實(shí)現(xiàn)了軟件的兩個(gè)目標(biāo):
1.需求很簡(jiǎn)單,輸出Hello World,這個(gè)程序完全滿足需求。
2.只有5行代碼的“軟件”無(wú)論是代碼質(zhì)量,還是可維護(hù)性,都相當(dāng)高,你想要把Hello改成Hi真的很輕松。
既然我們已經(jīng)實(shí)現(xiàn)了代碼的目標(biāo),要不要使用單元測(cè)試是無(wú)所謂的,同樣這么簡(jiǎn)單的代碼也沒人會(huì)使用GIT或SVN。
代碼量:5行
02、立簡(jiǎn)單計(jì)算器
接下來你寫了一個(gè)相對(duì)更復(fù)雜的程序,一個(gè)簡(jiǎn)單計(jì)算器。這個(gè)程序?qū)崿F(xiàn)了數(shù)字的加減乘除,整個(gè)程序共寫了大概50行代碼。這個(gè)程序需要單元測(cè)試嗎?
1.需求是對(duì)數(shù)字進(jìn)行加減乘除,這個(gè)程序滿足了需求。
2.你的代碼風(fēng)格很好(你已經(jīng)了解到代碼風(fēng)格很重要),你使用了縮進(jìn),良好的變量命名,邏輯也清晰,代碼的質(zhì)量和可維護(hù)性仍然相當(dāng)高,如果你想增加一個(gè)“求x的平方”功能,你輕而易舉就可以做到。
這個(gè)時(shí)候讓你去寫單元測(cè)試,你仍然會(huì)覺得那純粹是浪費(fèi)時(shí)間。
代碼量:50行
03、圖書管理系統(tǒng)
你想要做一個(gè)真正的實(shí)用系統(tǒng),給學(xué)校開發(fā)一個(gè)圖書管理系統(tǒng)。 你相信這個(gè)系統(tǒng)的代碼量比起計(jì)算器會(huì)很多(可能會(huì)有1000行)。你從書上看到有這樣一些方法可以簡(jiǎn)化你的開發(fā)工作:
1.工具庫(kù)(類似你家里的工具箱),使用工具庫(kù)帶來的好處是非常明顯的,假如你要實(shí)現(xiàn)“返回一個(gè)數(shù)字?jǐn)?shù)組中的最大值”,你只需要使用某個(gè)工具庫(kù)的Max()函數(shù),只需要1行代碼,而不是10行代碼自己實(shí)現(xiàn)。
2.MVC框架,雖然比起工具庫(kù)更復(fù)雜,需要花更多時(shí)間學(xué)習(xí),但MVC框架帶來的好處也非常明顯,輕而易舉調(diào)用數(shù)據(jù)庫(kù)(Model),實(shí)現(xiàn)簡(jiǎn)單的UI界面(View),實(shí)現(xiàn)了類似“書名為空的書不允許添加到數(shù)據(jù)庫(kù)”的一些邏輯(Controller)。
你最終很好的實(shí)現(xiàn)了這個(gè)系統(tǒng),基于MVC模型,你的代碼被很好的分割成了很多小的獨(dú)立的模塊:4個(gè)Controller,2個(gè)Model,4個(gè)View。并且在工具庫(kù)的幫助下,代碼量得到了縮減,每個(gè)模塊大概只有50行代碼(等同于一個(gè)簡(jiǎn)單計(jì)算器的代碼量)。這個(gè)系統(tǒng)需要單元測(cè)試嗎?
1.你實(shí)現(xiàn)了對(duì)圖書的添加、刪除、修改、借閱,你很好的滿足了需求(校長(zhǎng)表?yè)P(yáng)了你)。 2.得益于框架與庫(kù)的使用,你的代碼被很好的模塊化了,每個(gè)模塊都像一個(gè)“簡(jiǎn)單計(jì)算器”那樣簡(jiǎn)單,增加新功能,或修改現(xiàn)有功能似乎也沒有什么大麻煩,雖然會(huì)出現(xiàn)一些小bug,但很快就修復(fù)了,代碼質(zhì)量和可維護(hù)性都比較高。
既然你又實(shí)現(xiàn)了代碼的目標(biāo)——“完成需求,高代碼質(zhì)量和可維護(hù)性”,那好像也沒“單元測(cè)試”什么事,畢竟寫它要浪費(fèi)額外的功夫,而且也沒感覺到有多少好處。
代碼量:500行
04、大型庫(kù)存管理系統(tǒng)
你被一家IT公司雇傭了,你通過了面試,進(jìn)入了一個(gè)即將開啟的項(xiàng)目——為一家大的電商公司做一個(gè)庫(kù)存管理系統(tǒng)。
項(xiàng)目初期一切都很順利,技術(shù)上和你做過的圖書管理系統(tǒng)差不多。首先你了解了客戶的需求,然后根據(jù)他們的需求,使用你已經(jīng)掌握的MVC框架和一些庫(kù),實(shí)現(xiàn)了他們的需求。
你寫了30個(gè)Controller, 50個(gè)Model,50個(gè)View,每個(gè)模塊的代碼都達(dá)到了大概150行,總代碼達(dá)到了驚人的20000行!
你覺得自己很了不起,能hold住這么多代碼,這完全是得益于你的高智商,以及工作努力??蛻艉軡M意,老板也很滿意,你的自我感覺也很不錯(cuò)。
并且你發(fā)現(xiàn)了比單元測(cè)試更好的東西,面向?qū)ο缶幊蹋∣OP),或函數(shù)式編程(FP),無(wú)論是哪一種,你發(fā)現(xiàn)你可以把一個(gè)模塊里的150行堆砌在一起的代碼再提取成1個(gè)對(duì)象的15種方法,或者15個(gè)獨(dú)立的函數(shù)(具體怎么提取,你得看相關(guān)的書籍),OOP或FP像MVC模型一樣,成功的把你的代碼分割成了更小的組成部分,每個(gè)方法或函數(shù)里代碼都只有10行左右,你幾乎回到了“Hello World”時(shí)代。
你需要單元測(cè)試嗎?(你能保證你的系統(tǒng)沒有BUG嗎?)這個(gè)復(fù)雜系統(tǒng)是由1950個(gè)函數(shù)和方法組成,如果想要確定系統(tǒng)整體沒有BUG,就等同于確定組成這個(gè)系統(tǒng)的1950個(gè)函數(shù)和方法沒有BUG。
而單元測(cè)試就是做這個(gè)事情的,顯而易見,如果你寫了單元測(cè)試,并且每個(gè)函數(shù)都通過了,你就可以驕傲的說:這個(gè)系統(tǒng)沒有BUG!(當(dāng)然這是代碼的角度,而非功能和產(chǎn)品的角度)
05、結(jié)論
雖然,從絕對(duì)的角度說,單元測(cè)試很重要,但是,從相對(duì)的角度來講,小的代碼量,簡(jiǎn)單固定的需求,個(gè)人開發(fā),一錘子買賣等等都會(huì)讓單元測(cè)試顯得不那么重要,并且你一直開發(fā)的很舒服,這就是為什么有的人感受不到單元測(cè)試的重要性(這種情況下的確也許不用寫單元測(cè)試)。
記住,單元測(cè)試的威力更多不是體現(xiàn)在新代碼的編寫上,而是對(duì)已有代碼的更改。但程序員的智慧是有限的,系統(tǒng)的復(fù)雜度卻是無(wú)限的,隨著更大挑戰(zhàn)的到來,當(dāng)系統(tǒng)的復(fù)雜度超過了你的邏輯,記憶能力,你必須依靠別的工具來幫助你減少問題。
如果你現(xiàn)在在做一個(gè)較大的項(xiàng)目,這個(gè)項(xiàng)目的需求很多,所以你一直在開發(fā),你遇到了這樣的痛苦狀況:
1.客戶總能在使用中找出BUG;
2.每次代碼的改動(dòng),都會(huì)導(dǎo)致一些意想不到的BUG出現(xiàn)。這個(gè)時(shí)候,單元測(cè)試可以挽救你。






