為什么要進(jìn)行單測試.
1. 單元測試的目的
一個單元測試從整個系統(tǒng)中單獨(dú)檢驗(yàn)產(chǎn)品程序代碼的『一個單元』并檢查其得到的結(jié)果是否是預(yù)期的。要測試的『一個單元』其大小是依據(jù)一組連貫的功能的大小及介于一個類別及一個包(package)之間實(shí)際上的變化(varies)。其目的是在整合程序代碼到系統(tǒng)的其余部分之前先測試以便找出程序代碼中的臭蟲(bugs)。Junit等支持在Java程序代碼中撰寫單元測試。
在整合之前于系統(tǒng)其它部分隔離起來抓蟲的理由是因?yàn)槟鞘潜容^容易的找到臭蟲(亦即比較快且便宜)及比較容易修正問題(并顯示其解決方式是可行的)。
單元測試對于在初始整合一小部分程序代碼以及整合其余的改變之前提供了一些利益。如果有人需要變動現(xiàn)有的程序代碼,事實(shí)上單元測試仍然可以讓他對于其后的程序代碼更有信心;即他的改變不會破壞任何東西。愈好的單元測試讓人愈有信心--理想上測試必須在加入的新功能前也隨之更新。
2. 誰來撰寫單元測試及何時撰寫單元測試
程序代碼測試可能是非常乏味的,尤其是測試別人的程序,而當(dāng)你是一個程序設(shè)計(jì)師的時候尤甚。但程序設(shè)計(jì)師喜歡撰寫程序,因此為什么不讓程序設(shè)計(jì)師撰寫一些程序可以作為測試之用呢?
當(dāng)單元測試正確的實(shí)作可以幫助程序設(shè)計(jì)師變的更有生產(chǎn)力,而同時提升開發(fā)程序代碼的品質(zhì)。有一點(diǎn)你必須了解的是單元測試應(yīng)該是開發(fā)程序的一部份是很重要的;而且程序代碼的設(shè)計(jì)必須是可以測試的。目前的趨勢是在撰寫程序代碼之前要先撰寫單元測試,并且把焦點(diǎn)放在Java類別的接口及行為上。
先寫測試,再寫代碼的好處:
從技術(shù)上強(qiáng)制設(shè)計(jì)師先考慮一個類的功能,也是這個類提供給外部的接口,而不至于太早陷入它的細(xì)節(jié)。這是面向?qū)ο筇岢囊环N設(shè)計(jì)原則。
好的測試其實(shí)是一個好的文檔,這個類使用者往往可以通過查看這個類的測試代碼了解它的功能。特別的,如果你拿到別人的一個程序,對他寫測試是好的了解這個程序的功能的方法。 xp的原則是 make it simple,不是很推薦另外寫文檔,因?yàn)轫?xiàng)目在開發(fā)過程中往往處于變動中,如果在早期寫文檔,以后代碼變動后還得同步文檔,多了一個工作,而且由于項(xiàng)目時間緊往往文檔寫的不全或與代碼不一致,與其這樣,不如不寫。而如果在項(xiàng)目結(jié)束后再寫文檔,開發(fā)人員往往已經(jīng)忘記當(dāng)時寫代碼時的種種考慮,況且有下一個項(xiàng)目的壓力,管理人員也不愿意再為舊的項(xiàng)目寫文檔。導(dǎo)致以后維護(hù)的問題
沒有人能保證需求不變動,以往項(xiàng)目往往對需求的變動大為頭疼,害怕這個改動會帶來其它地方的錯誤。為此,除了設(shè)計(jì)好的結(jié)構(gòu)以分割項(xiàng)目外(松耦合),但如果有了測試,并已經(jīng)建立了一個好的測試框架,對于需求的變動,修改完代碼后,只要重新運(yùn)行測試代碼,如果測試通過,也保證了修改的成功,如果測試中出現(xiàn)錯誤,也會馬上發(fā)現(xiàn)錯在哪里。修改相應(yīng)的部分,再運(yùn)行測試,直至測試完全通過。
軟件公司里往往存在開發(fā)部門和測試部門之間的矛盾:由于開發(fā)和測試分為兩個部門,多了一層溝通的成本和時間,溝通往往會產(chǎn)生錯誤的發(fā)生。而且極易形成一個怪圈:開發(fā)人員為了趕任務(wù),寫了爛爛的代碼,把它扔給測試人員,然后寫其它的任務(wù),測試當(dāng)然是失敗的,又把代碼拿回去重寫,測試成了一個很頭疼的問題。這種怪圈的根源是責(zé)任不清,根據(jù) xp 中的規(guī)定:寫這個代碼的人必須為自己的代碼寫測試,而且只有測試通過,才算完成這個任務(wù)(這里的測試包括所有的測試,如果測試時發(fā)現(xiàn)由于你的程序?qū)е聞e的組的測試失敗,你有責(zé)任通知相關(guān)人員修改直至集成測試通過),這樣可以避免這類問題的發(fā)生。
簡而言之,如果程序設(shè)計(jì)師要寫一段代碼:
先用 junit 寫測試,然后再寫代碼;
寫完代碼,運(yùn)行測試,如果測試失敗,
修改代碼,運(yùn)行測試,直到測試成功。
如果以后對程序進(jìn)行修改,優(yōu)化 ( refactoring ),只要再運(yùn)行測試代碼。如果所有的測試都成功,則代碼修改完成。
3. 單元測試與Java Team開發(fā)的結(jié)合
Java下的team開發(fā),一般采用cvs(版本控制) + ant(項(xiàng)目管理) + junit(單元測試、集成測試)的模式:
每天早上上班,每個開發(fā)人員從 cvs server 獲取一個整個項(xiàng)目的工作拷貝。
拿到自己的任務(wù),先用 junit 寫的任務(wù)的測試代碼。
然后寫任務(wù)的代碼,運(yùn)行測試(單元測試),直到測試通過。
任務(wù)完成在下班前一兩個小時,各個開發(fā)人員把任務(wù)提交到cvs server。
然后由主管對整個項(xiàng)目運(yùn)行自動測試(集成測試),哪個測試出錯,找相關(guān)人員修改,直到所有測試通過。下班。。。
4. 測試控制工具中要有甚么?
無論誰來撰寫單元測試或何時撰寫單元測試,我們的焦點(diǎn)應(yīng)該放在檢驗(yàn)程序代碼;主要是在于產(chǎn)生錯誤的風(fēng)險(xiǎn)。如果設(shè)計(jì)文件包含被測試對象的使用情節(jié);便可成為好的測試來源。不管如何,這些情節(jié)寫得不是很明確;因?yàn)檫@些情節(jié)實(shí)際上是以設(shè)計(jì)觀點(diǎn)所寫的--因此適當(dāng)?shù)臏y試應(yīng)該有對等的情節(jié),換句話說,也是測試設(shè)計(jì)應(yīng)該盡可能的包含用戶實(shí)際使用程序時可能產(chǎn)生的動作或者過程。
另一個測試案例好的來源是在整合后從產(chǎn)品程序代碼當(dāng)中找到的問題,維修問題的處理方式往往值得封裝成為測試案例。
5. 為什么要使用Junit等工具呢?
前面的論述說明為什么我們需要測試控制工具,但為什么我們使用Junit這些工具呢?
首先,它們是完全Free的啦!。
第二點(diǎn),使用方便。
l 在你提升程序代碼的品質(zhì)時JUnit測試仍允許你更快速的撰寫程序
那聽起來似乎不是很直覺,但那是事實(shí)。當(dāng)你使用JUnit撰寫測試,你將花更少的時間除蟲,同時對你程序代碼的改變更 俱有信心。這個信心讓你更積極重整程序代碼并增加新的功能。沒有測試,對于重整及增加新功能你會變得沒有信心;因?yàn)槟悴恢烙猩趺礀|西會破壞產(chǎn)出的結(jié)果。采用一個綜合的測試系列,你可以在改變程序代碼之后快速的執(zhí)行多個測試并對于你的變動并未破壞任何東西感到有信心。在執(zhí)行測試時如果發(fā)現(xiàn)臭蟲,原始碼仍然清楚的在你腦中,因此很容易找到臭蟲。在JUnit中撰寫的測試幫助你以一種極 大(extreme)的步伐撰寫程序及快速的找出缺點(diǎn)。