4.4.1 調(diào)整周期
當(dāng)你開(kāi)發(fā)代碼的時(shí)候,你會(huì)設(shè)計(jì)一個(gè)應(yīng)用程序變成接口,然后實(shí)現(xiàn)接口所提出的功能.當(dāng)你進(jìn)行單元測(cè)試的時(shí)候,你通過(guò)一個(gè)方法的API來(lái)驗(yàn)證功能
4.4.2 TDD兩步走
前面,我們說(shuō)過(guò)通過(guò)[測(cè)試,編碼,(重復(fù)),提交]這樣一個(gè)流程,TDD加快了開(kāi)發(fā)的周期.可問(wèn)題在于這還遺漏了一個(gè)重要的步驟.更應(yīng)該像這樣來(lái)運(yùn)作:[測(cè)試,編碼,重構(gòu),(重復(fù)),提交].
TDD的核心原則是:
1. 在寫(xiě)新代碼之前寫(xiě)一個(gè)失敗的自動(dòng)測(cè)試.
2. 消除重復(fù).
消除重復(fù)這個(gè)步驟確保了你寫(xiě)的代碼不僅能通過(guò)測(cè)試,還具備可維護(hù)性.當(dāng)你清除了重復(fù)之后,你能夠增加內(nèi)聚,減少依賴(lài).這些都是長(zhǎng)時(shí)間保存而不變質(zhì)的代碼的特點(diǎn).
別的編碼實(shí)踐鼓勵(lì)我們編寫(xiě)可預(yù)知改變從而達(dá)到可維護(hù)性的代碼.與他們不同的是,TDD鼓勵(lì)我們通過(guò)消除重復(fù)來(lái)編寫(xiě)可維護(hù)的代碼.遵循這個(gè)實(shí)踐的開(kāi)發(fā)者發(fā)現(xiàn).有測(cè)試撐腰的并且劃分良好的代碼自然而然地可以簡(jiǎn)單而且安全地承受改變.TDD給了我們自信,讓我們的問(wèn)題解決,明天的問(wèn)題明天解決.
4.5 在開(kāi)發(fā)周期中的測(cè)試
在開(kāi)發(fā)周期的不同地方和不同時(shí)間都會(huì)有測(cè)試.讓我們首先介紹一下開(kāi)發(fā)生命周期,然后以它為基礎(chǔ)來(lái)決定何種類(lèi)型的測(cè)試將在何時(shí)被運(yùn)行.圖4.9給出了一個(gè)典型的開(kāi)發(fā)周期,這樣的一個(gè)開(kāi)發(fā)周期我們?cè)谛⌒突虼笮偷拈_(kāi)發(fā)中都廣泛應(yīng)用.
生命周期被分成四到五個(gè)平臺(tái)(platform)
開(kāi)發(fā)平臺(tái): 這是編碼發(fā)生的場(chǎng)所.它包含開(kāi)發(fā)者的工作站.它的一個(gè)重要的功能是提交(commit) 或check in(取決于所使用的術(shù)語(yǔ));這樣的提交會(huì)有幾次,提交到你的公共源代碼控制管理工具.一旦你提交了,其他人能開(kāi)始使用你所提交的東西了.但是只能提價(jià)能工作的部分也是很重要的.為了能知道它是否能正常工作, 一個(gè)典型的策略是采用自動(dòng)構(gòu)建,并且在每次上傳之后都運(yùn)行它.
集成平臺(tái)(integration platform):這個(gè)平臺(tái)的目的是集成各個(gè)不同部分來(lái)構(gòu)建應(yīng)用程序而且要確保他們?cè)谝黄鹉軈f(xié)調(diào)地工作.這一步是很有價(jià)值的,因?yàn)橥ǔD茉谶@兒發(fā)現(xiàn)問(wèn)題.是因?yàn)樗苤匾?所以我們希望它能自動(dòng)執(zhí)行.它被成為持續(xù)集成.并且,通過(guò)把自動(dòng)構(gòu)建應(yīng)用程序作為構(gòu)建過(guò)程的一部分,這也是可以達(dá)到的
驗(yàn)收平臺(tái)/壓力測(cè)試平臺(tái):取決于你的項(xiàng)目預(yù)算,這可以是一個(gè)或兩個(gè)平臺(tái).壓力測(cè)試平臺(tái)在加載以后執(zhí)行應(yīng)用程序,并驗(yàn)證它是正確的.驗(yàn)收平臺(tái)是項(xiàng)目的客戶(hù).
成品(前)平臺(tái)
讓我們來(lái)看一下測(cè)試是如何在開(kāi)發(fā)周期中發(fā)揮作用的.圖4.10說(shuō)明了在每一個(gè)平臺(tái)上你能進(jìn)行的不同種類(lèi)的測(cè)試:
在開(kāi)發(fā)平臺(tái),你執(zhí)行邏輯單元測(cè)試(這些測(cè)試是能脫離環(huán)境進(jìn)行的).這些測(cè)試執(zhí)行得非常快,你通常從你的IDE來(lái)執(zhí)行它們以驗(yàn)證你對(duì)你的代碼所做得任何改動(dòng)沒(méi)有損壞其他部分.在你提交代碼到你的SCM之前,你也可以通過(guò)你的自動(dòng)構(gòu)造來(lái)執(zhí)行它們.你應(yīng)該執(zhí)行集成單元測(cè)試
集成平臺(tái)通常會(huì)自動(dòng)運(yùn)行構(gòu)造過(guò)程,生成包,配置應(yīng)用程序,并且執(zhí)行單元測(cè)試和功能測(cè)試,通常只是所有功能測(cè)試得一個(gè)子集在集成開(kāi)發(fā)平臺(tái)下運(yùn)行,因?yàn)橄鄬?duì)于目標(biāo)平臺(tái),它只是一個(gè)簡(jiǎn)單的平臺(tái),缺少一些元素
在驗(yàn)收平臺(tái)/壓力平臺(tái)上,你將執(zhí)行和集成平臺(tái)相同的測(cè)試,此外,你還要運(yùn)行有壓力測(cè)試和負(fù)荷測(cè)試.驗(yàn)收平臺(tái)同終的運(yùn)行平臺(tái)非常相似,并且能夠執(zhí)行更多的功能測(cè)試.
盡管在預(yù)期的運(yùn)行平臺(tái)下測(cè)試是一個(gè)很好的習(xí)慣.這樣的話(huà)會(huì)保證你是在一個(gè)一切都是正確的環(huán)境下校驗(yàn)的.
4.6 小結(jié)
改變的步伐在加快,項(xiàng)目的時(shí)間框架在縮短,而我們需要對(duì)變化作出快速的反應(yīng).另外,開(kāi)發(fā)過(guò)程正在改變----讓開(kāi)發(fā)成為代碼的藝術(shù)還不夠,還應(yīng)當(dāng)讓開(kāi)發(fā)成為編寫(xiě)解決方案的藝術(shù).
為了能跟上迅速變化的腳步,我們必須打破異步開(kāi)發(fā)模式,在這種模式中,軟件測(cè)試是在開(kāi)發(fā)完成以后由另一個(gè)獨(dú)立的團(tuán)隊(duì)進(jìn)行的,當(dāng)改變和速度變得極為重要時(shí),把測(cè)試留到后不那么合適了.
第五章:Junit自動(dòng)化
在這一章里,我們將學(xué)習(xí)直接支持Junit的三個(gè)產(chǎn)品:Ant,Maven以及Eclipse.Ant和Maven是可以和任何Java編程環(huán)境配合使用的構(gòu)建工具,Eclipse是一個(gè)集成開(kāi)發(fā)環(huán)境(IDE).我們將會(huì)展示如何高效地結(jié)合使用Junit和這些環(huán)境,以及如何把Junit測(cè)試的執(zhí)行自動(dòng)化.在這章的后,你將會(huì)知道,如何在你的電腦上配置環(huán)境來(lái)構(gòu)建Java項(xiàng)目,包含如何執(zhí)行Junit測(cè)試以及如何創(chuàng)建Junit報(bào)告.
5.1 生命中的
為了使單元測(cè)試有效實(shí)用,它們必須是開(kāi)發(fā)流程的一部分.大部分的開(kāi)發(fā)周期開(kāi)始于從項(xiàng)目源代碼中導(dǎo)出模板.在進(jìn)行任何修改之前,謹(jǐn)慎的開(kāi)發(fā)者會(huì)首先運(yùn)行全套的測(cè)試工具.許多團(tuán)隊(duì)有工作庫(kù)必須通過(guò)所有單元測(cè)試的規(guī)定.在開(kāi)始你自己的任何開(kāi)發(fā)前,你必須留意沒(méi)有誰(shuí)違反這條”全綠規(guī)定”.你必須保證你的工作進(jìn)展是已知的基線(xiàn)開(kāi)始.
接下來(lái)是編寫(xiě)新的用例的代碼.如果你是測(cè)試驅(qū)動(dòng)開(kāi)發(fā)的實(shí)踐者,你會(huì)先開(kāi)始針對(duì)用例編寫(xiě)新的測(cè)試.一般來(lái)說(shuō),這項(xiàng)測(cè)試表明你的用例未被支持.一旦你寫(xiě)下了實(shí)現(xiàn)用例的代碼,狀態(tài)條將變綠,這樣你可以提交你的代碼了.
非TDD實(shí)踐者將實(shí)現(xiàn)用例并且編寫(xiě)測(cè)試驗(yàn)證.一旦狀態(tài)條變綠,代碼和測(cè)試可以提交了.
5.2 從Ant中執(zhí)行測(cè)試
編譯和測(cè)試像第三章中的DefaultController類(lèi)這樣一個(gè)單獨(dú)的類(lèi)是不難的.如果你的工具只是庫(kù)中Javac編譯器,那么編譯一個(gè)包含有多個(gè)類(lèi)的大項(xiàng)目將是令人頭痛的.在數(shù)目不斷增加的類(lèi)之間互相牽扯.于是越來(lái)越多的類(lèi)得處于classpath上以便編譯器能找到它們.在每次構(gòu)建中,只有一小部分類(lèi)會(huì)被修改,該編譯哪些類(lèi)也是問(wèn)題.在編譯之后手動(dòng)重新編譯你的Junit測(cè)試也同樣不方便.
幸運(yùn)的是,以上問(wèn)題的答案是令人難以置信的Ant.ant不僅是一個(gè)編譯程序的強(qiáng)有力工具,也是執(zhí)行Junit回歸測(cè)試的解決之道.
5.2.1 不可缺少的Ant
Apache的Ant是個(gè)讓你輕松地編譯和測(cè)試程序的構(gòu)建工具.它是構(gòu)建Java程序的事實(shí)標(biāo)準(zhǔn).讓Ant如此流行的一個(gè)原因是它不僅僅是個(gè)工具;ant是運(yùn)行工具的架構(gòu).除了可以使用Ant配置和啟動(dòng)編譯器,你還可以使用它來(lái)生成代碼,執(zhí)行JDBC查詢(xún),還有你將看到的Junit整套測(cè)試工具.
像許多現(xiàn)在的項(xiàng)目一樣,Ant使用一個(gè)XML文件來(lái)進(jìn)行配置.這個(gè)文件也是構(gòu)建文件(buildfile),默認(rèn)情況下被命名為build.xml.Ant的編譯文件描述了你想應(yīng)用在你的項(xiàng)目中的每一個(gè)任務(wù).任務(wù)可能是編譯java源碼.生成java文檔.
第二部分:測(cè)試策略
第一部分介紹用Junit進(jìn)行單元測(cè)試的基本知識(shí).然而,僅僅知道了Junit如何工作,或者如何把Unit用于簡(jiǎn)單的例子,這都是遠(yuǎn)遠(yuǎn)不夠的.尤其是當(dāng)把它用來(lái)測(cè)試一個(gè)真正的應(yīng)用程序的時(shí)候.所以,單獨(dú)的Junit是不夠的,你需要發(fā)展出一套測(cè)試策略,使你能夠?qū)σ恍┱鏄寣?shí)彈的程序進(jìn)行單元測(cè)試.主要問(wèn)題在于如何孤立地測(cè)試每個(gè)部分.你在寫(xiě)單元測(cè)試代碼時(shí),想要一點(diǎn)一點(diǎn)地測(cè)試應(yīng)用程序.那么,你如何把各個(gè)功能分離出來(lái),從而獨(dú)立地測(cè)試它們呢?第2部分解決了這個(gè)重要問(wèn)題..
第6章介紹了stub策略,它允許你孤立測(cè)試粗粒度的代碼部分.在第7章中,你會(huì)學(xué)習(xí)到叫mock objects的新技術(shù),它可以進(jìn)行孤立的細(xì)粒度測(cè)試.通過(guò)使用mock objects,你會(huì)發(fā)現(xiàn)這不僅僅是一種對(duì)代碼進(jìn)行單元測(cè)試的新方法,而且還是一種新的編程方法.第8章把你帶入一個(gè)全新的領(lǐng)域---在容器中對(duì)代碼進(jìn)行單元測(cè)試.現(xiàn)在,幾乎所有的代碼運(yùn)行在可與之交互的某些容器中.你會(huì)學(xué)到,當(dāng)J2EE代碼運(yùn)行在它的容器中時(shí),如何進(jìn)行單元測(cè)試.你還可以通過(guò)與mock objects方法進(jìn)行比較,從而了解這種策略的利弊.
讀完第二部分,你會(huì)熟悉用隔離方法對(duì)代碼進(jìn)行單元測(cè)試的這三種策略了.你將做好準(zhǔn)備,可以去應(yīng)付我們旅行的后一步:單元測(cè)試各種類(lèi)型的J2ee組件.