需要強調的是:測試是一個持續的過程。也就是說測試貫穿與開發的整個過程中,單元測試尤其適合于迭代增量式(iterative and incremental)的開發過程。Martin Fowler(有點兒像引用孔夫子的話)甚至認為:“在你不知道如何測試代碼之前,就不應該編寫程序。而一旦你完成了程序,測試代碼也應該完成。除非測試成功,你不能認為你編寫出了可以工作的程序。”我并不指望所有的開發人員都能有如此高的覺悟,這種層次也不是一蹴而就的。但我們一旦了解測試的目的和好處,自然會堅持在開發過程中引入測試。因為我們是測試新手,我們也不理會那些復雜的測試原理,先說一說最簡單的:測試就是比較預期的結果是否與實際執行的結果一致。假如一致則通過,否則失敗。看下面的例子:
我們目前所能做的就是盡量降低所付出的代價:我們編寫的測試代碼要能被維護人員輕易的讀取,我們編寫測試代碼要有一定的規范。最好IDE工具可以支持這些規范。好了,你所需要的就是JUnit。一個Open Source的項目。用其主頁上的話來說就是:“ JUnit是由 Erich Gamma 和 Kent Beck 編寫的一個回歸測試框架(regression testing framework)。用于Java開發人員編寫單元測試之用。”所謂框架就是Erich Gamma 和 Kent Beck 定下了一些條條框框,你編寫的測試代碼必須遵循這個條條框框:繼續某個類,實現某個接口。其實也就是我們前面所說的規范。好在JUnit目前得到了大多數軟件工程師的認可。遵循JUnit我們會得到很多的支持。回歸測試就是你不斷地對所編寫的代碼進行測試:編寫一些,測試一些,調試一些,然后循環這一過程,你會不斷地重復先前的測試,哪怕你正編寫其他的類,由于軟件熵的存在,你可能在編寫第五個類的時候發現,第五個類的某個操作會導致第二個類的測試失敗。通過回歸測試我們抓住了這條大Bug。
二、JUnit簡介及為什么要使用JUint
JUnit就是對程序代碼進行單元測試的一種Java框架。通過每次修改程序之后測試代碼,程序員就可以保證代碼的的少量變動不會破壞整個系統。要不是有Junit這樣的自動化測試工具,代碼的的反復測試簡直會把人累死而且還可能不準確。現在好了,測試過程可以頻繁進行而且還是自動的,所以你可以令程序錯誤降低到最少。它寫的是單元測試(Unit Test):軟件工程里的白盒測試,就是測試某個類的某個方法的功能。XP 中推崇的 test first design 就是基于以上的技術。
從技術上強制你先考慮一個類的功能,也就是這個類提供給外部的接口,而不至于太早陷入它的細節。這是面向對象提倡的一種設計原則。好的測試其實就是一個好的文檔,這個類使用者往往可以通過查看這個類的測試代碼了解它的功能。非凡的,假如你拿到別人的一個程序,對他寫測試是最好的了解這個程序的功能的方法。 xp的原則是 make it simple,不是很推薦另外寫文檔,因為項目在開發過程中往往處于變動中,假如在早期寫文檔,以后代碼變動后還得同步文檔,多了一個工作,而且由于項目時間緊往往文檔寫的不全或與代碼不一致,與其這樣,不如不寫。而假如在項目結束后再寫文檔,開發人員往往已經忘記當時寫代碼時的種種考慮,況且有下一個項目的壓力,治理人員也不愿意再為舊的項目寫文檔,導致以后維護的問題。沒有人能保證需求不變動,以往項目往往對需求的變動大為頭疼,害怕這個改動會帶來其他地方的錯誤。為此,除了設計好的結構以分割項目外(松耦合),但假如有了測試,并已經建立了一個好的測試框架,對于需求的變動,修改完代碼后,只要重新運行測試代碼,假如測試通過,也就保證了修改的成功,假如測試中出現錯誤,也會馬上發現錯在哪里,修改相應的部分,再運行測試,直至測試完全通過。
軟件公司里往往存在開發部門和測試部門之間的矛盾:由于開發和測試分為兩個部門,多了一層溝通的成本和時間,溝通往往會產生錯誤的發生。而且極易形成一個怪圈:開發人員為了趕任務,寫了爛爛的代碼,就把它扔給測試人員,然后寫其他的任務,測試當然是失敗的,又把代碼拿回去重寫,而且在國內往往一個軟件公司技術最差的部門就是測試部門(好的人都跑去寫代碼了),測試就成了一個很頭疼的問題。這種怪圈的根源是責任不清,根據 xp 中的規定:寫這個代碼的人必須為自己的代碼寫測試,而且只有測試通過,才算完成這個任務(這里的測試包括所有的測試,假如測試時發現由于你的程序導致別的模塊的測試失敗,你有責任通知相關人員修改直至集成測試通過),這樣就可以避免這類問題的發生。