25 測(cè)試驅(qū)動(dòng)開(kāi)發(fā)模式
準(zhǔn)備兩個(gè)TODO-List一個(gè)用于當(dāng)前,一個(gè)用于最近
當(dāng)發(fā)現(xiàn)有事情要做的時(shí)候,對(duì)其優(yōu)先級(jí)進(jìn)行判斷,將其放到當(dāng)前或者以后。
集中注意力于當(dāng)前要做的事情
斷言優(yōu)先
寫(xiě)Case的時(shí)候,一開(kāi)始就寫(xiě)斷言,從測(cè)試完成時(shí)能通過(guò)的斷言開(kāi)始寫(xiě)。
測(cè)試數(shù)據(jù)
測(cè)試數(shù)據(jù)要使用容易讓人理解的數(shù)據(jù),不要為了編排數(shù)據(jù)而編排數(shù)據(jù)
不要用同一個(gè)常量來(lái)表達(dá)多種一絲。另外也可以使用真實(shí)數(shù)據(jù)進(jìn)行測(cè)試。
盡量讓測(cè)試的行為和數(shù)據(jù)容易理解,比如不使用常量,而是直接使用數(shù)字。在assert中加入斷言要測(cè)試的目的的文字說(shuō)明
26 不可運(yùn)行狀態(tài)
一步測(cè)試(One Step Test)
從計(jì)劃列表中選擇具有指導(dǎo)意義而且有把握實(shí)現(xiàn)的測(cè)試去完成它。??
啟動(dòng)測(cè)試(Starter Test)
從測(cè)試某個(gè)實(shí)質(zhì)上不做任何工作的操作開(kāi)始,這樣的測(cè)試一般能很快工作。而一個(gè)做實(shí)際工作的功能的測(cè)試可能需要等你解決很多問(wèn)題,比如:這個(gè)操作隸屬于哪里?正確的輸入是什么?對(duì)應(yīng)的正確輸出是什么?等等。結(jié)果是其長(zhǎng)期無(wú)法通過(guò)。
回歸測(cè)試(Regression Test)
對(duì)于一個(gè)錯(cuò)誤情況,編寫(xiě)一個(gè)針對(duì)該錯(cuò)誤的,會(huì)出錯(cuò)的,盡可能小的測(cè)試。
27測(cè)試模式
子測(cè)試(Child Test)如果一個(gè)測(cè)試太大以至于難以運(yùn)行起來(lái),那么可以先把該測(cè)試給分解成幾個(gè)小的測(cè)試,并注釋掉本測(cè)試。等這些小測(cè)試通過(guò)之后再繼續(xù)這個(gè)大的測(cè)試??
模擬對(duì)象(Mock Object)
如何測(cè)試一個(gè)依賴于昂貴的且復(fù)雜的資源的對(duì)象?創(chuàng)建一個(gè)這些資源的模擬版本。
自分流(self Shunt)
如何測(cè)試對(duì)象間是否正常交互?讓測(cè)試對(duì)象于測(cè)試用例而不是期望的對(duì)象進(jìn)行交互。
需要讓測(cè)試用例類實(shí)現(xiàn)所要交互的類的接口。從而進(jìn)行測(cè)試所實(shí)現(xiàn)的方法會(huì)被正確的調(diào)用。
日志字符串(Log String)
如何才能測(cè)試使消息調(diào)用順序是正確的?將日志保存在字符串中,當(dāng)調(diào)用一個(gè)消息時(shí),就向字符串尾部追加相應(yīng)的信息。
清掃測(cè)試死角(Crash Test Dummy)
如何測(cè)試到不大可能被調(diào)用的錯(cuò)誤代碼呢?使用一種特殊的對(duì)象調(diào)用它,這個(gè)對(duì)象拋出一個(gè)異常而不做任何實(shí)際工作。比如實(shí)現(xiàn)一個(gè)匿名File子類,只實(shí)現(xiàn)其createNewFile方法,方法中拋出一個(gè)異常,通過(guò)這種方式來(lái)測(cè)試文件系統(tǒng)滿了的情況。
不完整測(cè)試(Broken Test)
留下半截句子或者一個(gè)沒(méi)有通過(guò)的測(cè)試用例可以保證你離開(kāi)代碼一段時(shí)間之后依然能較快的回憶起原先的想法。
提交前保證所有測(cè)試運(yùn)行通過(guò)
當(dāng)你在團(tuán)隊(duì)中變成時(shí)如何結(jié)束一段編碼工作?讓所有測(cè)試運(yùn)行起來(lái)。
注釋掉一些測(cè)試代碼使測(cè)試套件通過(guò)是要嚴(yán)格禁止的。
28可運(yùn)行模式
偽實(shí)現(xiàn)(直到你成功)測(cè)試不能通過(guò)時(shí)首先應(yīng)該執(zhí)行什么?可以返回一個(gè)常量。一旦你能使測(cè)試運(yùn)行起來(lái),那個(gè)常量就會(huì)逐漸換成用變量表示的表達(dá)式。這個(gè)方法可以從心理上讓我們感到滿足,可以讓我們集中注意力于當(dāng)前要解決的問(wèn)題。
三角法(Triangulation)
怎樣可以更適當(dāng)?shù)乩脺y(cè)試推動(dòng)抽象呢?只有當(dāng)你有兩個(gè)或兩個(gè)以上的例子時(shí),你才能進(jìn)行抽象。使用兩個(gè)針對(duì)同一個(gè)測(cè)試目標(biāo)的測(cè)試?yán)樱ɑ驍嘌裕诖嘶A(chǔ)上對(duì)該測(cè)試目標(biāo)的實(shí)現(xiàn)進(jìn)行抽象并實(shí)現(xiàn)。
顯明實(shí)現(xiàn)(Obvious Implementation)
直接實(shí)現(xiàn)簡(jiǎn)單的操作。
從一到多(One to Many)
怎樣實(shí)現(xiàn)一個(gè)作用于對(duì)象集合體的操作呢?首先在非集合體中實(shí)現(xiàn),然后使之作用于集合體。
32 掌握TDD
什么可以不必測(cè)試?應(yīng)該測(cè)試:條件部分、循環(huán)部分、操作部分、多態(tài)性。除了不信任,否則不要測(cè)試其他來(lái)源的代碼。
怎樣知道自己的測(cè)試沒(méi)有疏漏呢?
一些預(yù)示著設(shè)計(jì)存在這缺陷的特征:
過(guò)長(zhǎng)的設(shè)置代碼——如果為了一個(gè)簡(jiǎn)單的斷言,需要花費(fèi)上百行代碼創(chuàng)建對(duì)象,那么肯定有哪兒不對(duì)勁兒。對(duì)象太大,需要分割。
冗余的設(shè)置代碼——如果你無(wú)法為公共代碼找到一個(gè)存放它的公共場(chǎng)所的話,那么就表明有太多的對(duì)象過(guò)于緊密地聯(lián)系在一起了。
過(guò)長(zhǎng)的測(cè)試運(yùn)行時(shí)間——這樣測(cè)試不會(huì)被經(jīng)常運(yùn)行,同時(shí)也暗示著對(duì)系統(tǒng)的方方面面進(jìn)行測(cè)試是困難的。這種測(cè)試?yán)щy是一種設(shè)計(jì)問(wèn)題,并且需要在設(shè)計(jì)時(shí)就被提出來(lái)。
脆弱的測(cè)試——意外中斷的測(cè)試說(shuō)明應(yīng)用的某一部分出人意料地存在對(duì)另一部分的影響。你需要對(duì)系統(tǒng)進(jìn)行設(shè)計(jì),要么打破聯(lián)系,要么將兩部分合并,直到這種影響消失為止。
你需要多少反饋?
測(cè)試驅(qū)動(dòng)的開(kāi)發(fā)對(duì)測(cè)試的觀點(diǎn)就是注重實(shí)效。在測(cè)試驅(qū)動(dòng)開(kāi)發(fā)中,測(cè)試從某種意義上說(shuō)是一種達(dá)到目的的手段——達(dá)到充滿自信地編寫(xiě)代碼的目的。如果我們對(duì)實(shí)現(xiàn)有充分了解,不用測(cè)試就能擁有自信的話,那么就沒(méi)有必要編寫(xiě)測(cè)試了。
什么時(shí)候應(yīng)該刪除測(cè)試?
如果刪除一個(gè)測(cè)試降低了你對(duì)整個(gè)系統(tǒng)功能的信心,那么就不要?jiǎng)h除。
如果你有兩個(gè)測(cè)試,走的是同一條路,但對(duì)讀者來(lái)說(shuō)講述的是不同的情形的話,那么就應(yīng)該原封不動(dòng)的保留。
如果有兩個(gè)測(cè)試,它們就自信和溝通而言都是冗余的,那么就刪除其中用處最小的那個(gè)。
如何中途轉(zhuǎn)向測(cè)試驅(qū)動(dòng)開(kāi)發(fā)?
首先限定修改的范圍。對(duì)于該范圍外的可以簡(jiǎn)化的地方先不動(dòng)手。
其次,必須打破測(cè)試與重構(gòu)之間的僵局。可以先通過(guò)其他方式獲取反饋,如系統(tǒng)測(cè)試,然后使用這些反饋進(jìn)行修改。通過(guò)這種方式逐漸的讓一直在改變的部分轉(zhuǎn)向測(cè)試驅(qū)動(dòng)。