JUnit實戰篇 (一)
修訂者:黃 凱
E_mail:hk_sz@163.com
前言
由于現在公司進行Unit Test Case的整理階段,所以抽空對Junit進行了一下了解,以下是集合了眾家所長之精華(考慮的是按我的思路總結的,也許不能完全表達作者的思路,所以在附錄中有所有我參考的文章地址,大家不妨去看看原文)。
一、測試的概念
長期以來,我所接觸的軟件開發人員很少有人能在開發的過程中進行測試工作。大部分的項目都是在最終驗收的時候編寫測試文檔,有些項目甚至沒有測試文檔,F在情況有了改變。我們一直提倡UML、RUP、軟件工程、CMM,目的只有一個,提高軟件編寫的質量。舉一個極端的例子:如果你是一個超級程序設計師,一個傳奇般的人物(你可以一邊喝咖啡,一邊聽著音樂,同時編寫這操作系統中關于進程調度的模塊,而且兩天時間內就完成了。。我真得承認,有這樣的人(那個編寫UNIX中的vi編輯器的家伙就是這種人)。然而非常遺憾的是這些神仙們并沒有留下任何關于如何修成正果的README,所以我們這些凡人--在同一時間只能將注意力集中到若干點(據科學統計,我并不太相信,一般的人只能同時考慮最多7個左右的問題,高手可以達到12個左右),而不能既縱覽全局又了解細節--只能期望于其他的方式來保證我們所編寫的軟件質量。
為了說明我們這些凡人是如何的笨。有一個聰明人提出了軟件熵(software entropy)的概念:一個程序從設計很好的狀態開始,隨著新的功能不斷地加入,程序逐漸地失去了原有的結構,最終變成了一團亂麻。你可能會爭辯,在這個例子中,設計很好的狀態實際上并不好,如果好的話,就不會發生你所說的情況。是的,看來你變聰明了,可惜你還應該注意到兩個問題:1)我們不能指望在恐龍紀元(大概是十年前)設計的結構到了現在也能適用吧;2)擁有簽字權的客戶代表可不理會加入一個新功能是否會對軟件的結構有什么影響,即便有影響也是程序設計人員需要考慮的問題。如果你拒絕加入這個你認為致命的新功能,那么你很可能就失去了你的住房貸款和面包(對中國工程師來說也許是米飯或面條,要看你是南方人還是北方人)。
另外,需要說明的是我看過的一些講解測試的書都沒有我寫的這么有人情味(不好意思...)。我希望看到這篇文章的兄弟姐妹能很容易地接受測試的概念,并付諸實施。所以有些地方寫的有些夸張,歡迎對測試有深入理解的兄弟姐妹能體察民情,并不吝賜教。
好了,我們現在言歸正傳。要測試,就要明白測試的目的。我認為測試的目的很簡單也極具吸引力:寫出高質量的軟件并解決軟件熵這一問題。想象一下,如果你寫的軟件和Richard Stallman(GNU、FSF的頭兒)寫的一樣有水準的話,是不是很有成就感?如果你一直保持這種高水準,我保證你的薪水也會有所變動。
測試也分類,白箱測試、黑箱測試、單元測試、集成測試、功能測試...。我們先不管有多少分類,如何分類。先看那些對我們有用的分類,關于其他的測試,有興趣的人可參閱其他資料。白箱測試是指在知道被測試的軟件如何(How)完成功能和完成什么樣(What)的功能的條件下所作的測試。一般是由開發人員完成。因為開發人員最了解自己編寫的軟件。本文也是以白箱測試為主。黑箱測試則是指在知道被測試的軟件完成什么樣(What)的功能的條件下所作的測試。一般是由測試人員完成。黑箱測試不是我們的重點。本文主要集中在單元測試上,單元測試是一種白箱測試。目的是驗證一個或若干個類是否按所設計的那樣正常工作。集成測試則是驗證所有的類是否能互相配合,協同完成特定的任務,目前我們暫不關心它。下面我所提到的測試,除非特別說明,一般都是指單元測試。
需要強調的是:測試是一個持續的過程。也就是說測試貫穿與開發的整個過程中,單元測試尤其適合于迭代增量式(iterative and incremental)的開發過程。Martin Fowler(有點兒像引用孔夫子的話)甚至認為:“在你不知道如何測試代碼之前,就不應該編寫程序。而一旦你完成了程序,測試代碼也應該完成。除非測試成功,你不能認為你編寫出了可以工作的程序!蔽也⒉恢竿械拈_發人員都能有如此高的覺悟,這種層次也不是一蹴而就的。但我們一旦了解測試的目的和好處,自然會堅持在開發過程中引入測試。因為我們是測試新手,我們也不理會那些復雜的測試原理,先說一說最簡單的:測試就是比較預期的結果是否與實際執行的結果一致。如果一致則通過,否則失敗?聪旅娴睦樱
//將要被測試的類
public class Car
{
public int getWheels()
{
return 4;
}
}
//執行測試的類
public class testCar
{
public static void main(String[] args)
{
testCar myTest = new testCar();
myTest.testGetWheels();
}
public void testGetWheels ()
{
int expectedWheels = 5;
Car myCar =new Car();
if (expectedWheels==myCar.getWheels())
System.out.println("test [Car]: getWheels works perfected!");
else
System.out.println("test [Car]: getWheels DOESN´T work!");
}
}
如果你立即動手寫了上面的代碼,你會發現兩個問題:
第一,如果你要執行測試的類testCar,你必須必須手工敲入如下命令:
[Windows] D:>java testCar
[Unix] % java testCar
即便測試如例示的那樣簡單,你也有可能不愿在每次測試的時候都敲入上面的命令,而希望在某個集成環境中(IDE)點擊一下鼠標就能執行測試。后面的章節會介紹到這些問題。
第二,如果沒有一定的規范,測試類的編寫將會成為另一個需要定義的標準。沒有人希望查看別人是如何設計測試類的。如果每個人都有不同的設計測試類的方法,光維護被測試的類就夠煩了,誰還顧得上維護測試類?另外有一點我不想提,但是這個問題太明顯了,測試類的代碼多于被測試的類!這是否意味這雙倍的工作?不!
1) 不論被測試類-Car 的 getWheels 方法如何復雜,測試類-testCar 的testGetWheels 方法只會保持一樣的代碼量。
2)提高軟件的質量并解決軟件熵這一問題并不是沒有代價的。testCar就是代價。
我們目前所能做的就是盡量降低所付出的代價:我們編寫的測試代碼要能被維護人員容易的讀取,我們編寫測試代碼要有一定的規范。最好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這樣的自動化測試工具,代碼的的反復測試簡直會把人累死而且還可能不準確,F在好了,測試過程可以頻繁進行而且還是自動的,所以你可以令程序錯誤降低到最少。它寫的是單元測試(Unit Test):軟件工程里的白盒測試,就是測試某個類的某個方法的功能。XP 中推崇的 test first design 就是基于以上的技術。
如果你要寫一段代碼:
1. 先用 junit 寫測試,然后再寫代碼
2. 寫完代碼,運行測試,測試失敗
3. 修改代碼,運行測試,直到測試成功
如果以后對程序進行修改,優化 ( refactoring ),只要再運行測試代碼,如果所有的測試都成功,則代碼修改完成。
Java 下的 team 開發,一般采用 cvs(版本控制) + ant(項目管理) + junit(集成測試) 的模式:
1. 每天早上上班,每個開發人員從 cvs server 獲取一個整個項目的工作拷貝;
2. 拿到自己的任務,先用 junit 寫今天的任務的測試代碼;
3. 然后寫今天任務的代碼,運行測試,直到測試通過,任務完成;
4. 在下班前一兩個小時,各個開發人員把任務提交到 cvs server;
5. 然后由主管對整個項目運行自動測試,哪個測試出錯,就找相關人員修改,直到所有測試通過。下班...
先寫測試,再寫代碼的好處:
從技術上強制你先考慮一個類的功能,也就是這個類提供給外部的接口,而不至于太早陷入它的細節。這是面向對象提倡的一種設計原則。好的測試其實就是一個好的文檔,這個類使用者往往可以通過查看這個類的測試代碼了解它的功能。特別的,如果你拿到別人的一個程序,對他寫測試是最好的了解這個程序的功能的方法。 xp的原則是 make it simple,不是很推薦另外寫文檔,因為項目在開發過程中往往處于變動中,如果在早期寫文檔,以后代碼變動后還得同步文檔,多了一個工作,而且由于項目時間緊往往文檔寫的不全或與代碼不一致,與其這樣,不如不寫。而如果在項目結束后再寫文檔,開發人員往往已經忘記當時寫代碼時的種種考慮,況且有下一個項目的壓力,管理人員也不愿意再為舊的項目寫文檔,導致以后維護的問題。沒有人能保證需求不變動,以往項目往往對需求的變動大為頭疼,害怕這個改動會帶來其他地方的錯誤。為此,除了設計好的結構以分割項目外(松耦合),但如果有了測試,并已經建立了一個好的測試框架,對于需求的變動,修改完代碼后,只要重新運行測試代碼,如果測試通過,也就保證了修改的成功,如果測試中出現錯誤,也會馬上發現錯在哪里,修改相應的部分,再運行測試,直至測試完全通過。
軟件公司里往往存在開發部門和測試部門之間的矛盾:由于開發和測試分為兩個部門,多了一層溝通的成本和時間,溝通往往會產生錯誤的發生。而且極易形成一個怪圈:開發人員為了趕任務,寫了爛爛的代碼,就把它扔給測試人員,然后寫其他的任務,測試當然是失敗的,又把代碼拿回去重寫,而且在國內往往一個軟件公司技術最差的部門就是測試部門(好的人都跑去寫代碼了),測試就成了一個很頭疼的問題。這種怪圈的根源是責任不清,根據 xp 中的規定:寫這個代碼的人必須為自己的代碼寫測試,而且只有測試通過,才算完成這個任務(這里的測試包括所有的測試,如果測試時發現由于你的程序導致別的模塊的測試失敗,你有責任通知相關人員修改直至集成測試通過),這樣就可以避免這類問題的發生。
參考
JUnit實施
作者:eric 原址:http://www.neweasier.com/article/2002-08-07/1028723459.html
怎樣使用Junit Framework進行單元測試的編寫
作者:cinc 原址:http://www.chinaunix.net/bbsjh/14/546.html
主要是引用了cinc的評論,至于申文波先生的《怎樣使用Junit Framework進行單元測試的編寫》原文我建議大家有時間看一下,寫得很好,我這里沒有整合進來。
創建Junit測試案例
作者: BUILDER.COM 原址:http://www.zdnet.com.cn/developer/code/story/0,2000081534,39033729,00.htm
文章來源于領測軟件測試網 http://www.kjueaiud.com/
版權所有(C) 2003-2010 TestAge(領測軟件測試網)|領測國際科技(北京)有限公司|軟件測試工程師培訓網 All Rights Reserved
北京市海淀區中關村南大街9號北京理工科技大廈1402室 京ICP備10010545號-5
技術支持和業務聯系:info@testage.com.cn 電話:010-51297073
老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月