欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
應用JUnit實(shí)施單元測試
應用JUnit實(shí)施單元測試(原創(chuàng )作者:eric )


(獻給想保證java coding軟件質(zhì)量的朋友們)
--------------------------------------------------------------------------------

測試的概念

長(cháng)期以來(lái),我所接觸的軟件開(kāi)發(fā)人員很少有人能在開(kāi)發(fā)的過(guò)程中進(jìn)行測試工作。大部分的項目都是在最終驗收的時(shí)候編寫(xiě)測試文檔。有些項目甚至沒(méi)有測試文檔?,F在情況有了改變。我們一直提倡UML、RUP、軟件工程、CMM,目的只有一個(gè),提高軟件編寫(xiě)的質(zhì)量。舉一個(gè)極端的例子:如果你是一個(gè)超級程序設計師,一個(gè)傳奇般的人物。(你可以一邊喝咖啡,一邊聽(tīng)著(zhù)音樂(lè ),同時(shí)編寫(xiě)這操作系統中關(guān)于進(jìn)程調度的模塊,而且兩天時(shí)間內就完成了?。┪艺娴贸姓J,有這樣的人。(那個(gè)編寫(xiě)UNIX中的vi編輯器的家伙就是這種人。)然而非常遺憾的是這些神仙們并沒(méi)有留下如何修成正果的README。所以我們這些凡人--在同一時(shí)間只能將注意力集中到若干點(diǎn)(據科學(xué)統計,我并不太相信,一般的人只能同時(shí)考慮最多7個(gè)左右的問(wèn)題,高手可以達到12個(gè)左右),而不能既縱覽全局又了解細節--只能期望于其他的方式來(lái)保證我們所編寫(xiě)的軟件質(zhì)量。

為了說(shuō)明我們這些凡人是如何的笨。有一個(gè)聰明人提出了軟件熵(software entropy)的概念:一個(gè)程序從設計很好的狀態(tài)開(kāi)始,隨著(zhù)新的功能不斷地加入,程序逐漸地失去了原有的結構,最終變成了一團亂麻。你可能會(huì )爭辯,在這個(gè)例子中,設計很好的狀態(tài)實(shí)際上并不好,如果好的話(huà),就不會(huì )發(fā)生你所說(shuō)的情況。是的,看來(lái)你變聰明了,可惜你還應該注意到兩個(gè)問(wèn)題:1)我們不能指望在恐龍紀元(大概是十年前)設計的結構到了現在也能適用吧。2)擁有簽字權的客戶(hù)代表可不理會(huì )加入一個(gè)新功能是否會(huì )對軟件的結構有什么影響,即便有影響也是程序設計人員需要考慮的問(wèn)題。如果你拒絕加入這個(gè)你認為致命的新功能,那么你很可能就失去了你的住房貸款和面包(對中國工程師來(lái)說(shuō)也許是米飯或面條,要看你是南方人還是北方人)。

另外,需要說(shuō)明的是我看過(guò)的一些講解測試的書(shū)都沒(méi)有我寫(xiě)的這么有人情味(不好意思...)。我希望看到這片文章的兄弟姐妹能很容易地接受測試的概念,并付諸實(shí)施。所以有些地方寫(xiě)的有些夸張,歡迎對測試有深入理解的兄弟姐妹能體察民情,并不吝賜教。

好了,我們現在言歸正傳。要測試,就要明白測試的目的。我認為測試的目的很簡(jiǎn)單也極具吸引力:寫(xiě)出高質(zhì)量的軟件并解決軟件熵這一問(wèn)題。想象一下,如果你寫(xiě)的軟件和Richard Stallman(GNU、FSF的頭兒)寫(xiě)的一樣有水準的話(huà),是不是很有成就感?如果你一致保持這種高水準,我保證你的薪水也會(huì )有所變動(dòng)。

測試也分類(lèi),白箱測試、黑箱測試、單元測試、集成測試、功能測試...。我們先不管有多少分類(lèi),如何分類(lèi)。先看那些對我們有用的分類(lèi),關(guān)于其他的測試,有興趣的人可參閱其他資料。白箱測試是指在知道被測試的軟件如何(How)完成功能和完成什么樣(What)的功能的條件下所作的測試。一般是由開(kāi)發(fā)人員完成。因為開(kāi)發(fā)人員最了解自己編寫(xiě)的軟件。本文也是以白箱測試為主。黑箱測試則是指在知道被測試的軟件完成什么樣(What)的功能的條件下所作的測試。一般是由測試人員完成。黑箱測試不是我們的重點(diǎn)。本文主要集中在單元測試上,單元測試是一種白箱測試。目的是驗證一個(gè)或若干個(gè)類(lèi)是否按所設計的那樣正常工作。集成測試則是驗證所有的類(lèi)是否能互相配合,協(xié)同完成特定的任務(wù),目前我們暫不關(guān)心它。下面我所提到的測試,除非特別說(shuō)明,一般都是指單元測試。

需要強調的是:測試是一個(gè)持續的過(guò)程。也就是說(shuō)測試貫穿與開(kāi)發(fā)的整個(gè)過(guò)程中,單元測試尤其適合于迭代增量式(iterative and incremental)的開(kāi)發(fā)過(guò)程。Martin Fowler(有點(diǎn)兒像引用孔夫子的話(huà))甚至認為:“在你不知道如何測試代碼之前,就不應該編寫(xiě)程序。而一旦你完成了程序,測試代碼也應該完成。除非測試成功,你不能認為你編寫(xiě)出了可以工作的程序。”我并不指望所有的開(kāi)發(fā)人員都能有如此高的覺(jué)悟,這種層次也不是一蹴而就的。但我們一旦了解測試的目的和好處,自然會(huì )堅持在開(kāi)發(fā)過(guò)程中引入測試。

因為我們是測試新手,我們也不理會(huì )那些復雜的測試原理,先說(shuō)一說(shuō)最簡(jiǎn)單的:測試就是比較預期的結果是否與實(shí)際執行的結果一致。如果一致則通過(guò),否則失敗??聪旅娴睦樱?


//將要被測試的類(lèi)
public class Car {
    public int getWheels() {
return 4;
}
}

//執行測試的類(lèi)
public class testCar {
public static void main(String[] args) {
testCar myTest = new testCar();
myTest.testGetWheels();
}

public testGetWheels() {
int expectedWheels = 4;
Car myCar = Car();
if (expectedWheels==myCar.getWheels()) 
System.out.println("test [Car]: getWheels works perfected!");
else
System.out.println("test [Car]: getWheels DOESN‘T work!");
}
}

如果你立即動(dòng)手寫(xiě)了上面的代碼,你會(huì )發(fā)現兩個(gè)問(wèn)題,第一,如果你要執行測試的類(lèi)testCar,你必須必須手工敲入如下命令:

[Windows] d:>;java testCar 
   [Unix] % java testCar

即便測試如例示的那樣簡(jiǎn)單,你也有可能不愿在每次測試的時(shí)候都敲入上面的命令,而希望在某個(gè)集成環(huán)境中(IDE)點(diǎn)擊一下鼠標就能執行測試。后面的章節會(huì )介紹到這些問(wèn)題。第二,如果沒(méi)有一定的規范,測試類(lèi)的編寫(xiě)將會(huì )成為另一個(gè)需要定義的標準。沒(méi)有人希望查看別人是如何設計測試類(lèi)的。如果每個(gè)人都有不同的設計測試類(lèi)的方法,光維護被測試的類(lèi)就夠煩了,誰(shuí)還顧得上維護測試類(lèi)?另外有一點(diǎn)我不想提,但是這個(gè)問(wèn)題太明顯了,測試類(lèi)的代碼多于被測試的類(lèi)!這是否意味這雙倍的工作?不!1)不論被測試類(lèi)-Car 的 getWheels 方法如何復雜,測試類(lèi)-testCar 的testGetWheels 方法只會(huì )保持一樣的代碼量。2)提高軟件的質(zhì)量并解決軟件熵這一問(wèn)題并不是沒(méi)有代價(jià)的。testCar就是代價(jià)。

我們目前所能做的就是盡量降低所付出的代價(jià):我們編寫(xiě)的測試代碼要能被維護人員容易的讀取,我們編寫(xiě)測試代碼要有一定的規范。最好IDE工具可以支持這些規范。 好了,你所需要的就是JUnit。一個(gè)Open Source的項目。用其主頁(yè)上的話(huà)來(lái)說(shuō)就是:“JUnit是由 Erich Gamma 和 Kent Beck 編寫(xiě)的一個(gè)回歸測試框架(regression testing framework)。用于Java開(kāi)發(fā)人員編寫(xiě)單元測試之用。”所謂框架就是 Erich Gamma 和 Kent Beck 定下了一些條條框框,你編寫(xiě)的測試代碼必須遵循這個(gè)條條框框:繼承某個(gè)類(lèi),實(shí)現某個(gè)接口。其實(shí)也就是我們前面所說(shuō)的規范。好在JUnit目前得到了大多數軟件工程師的認可。遵循JUnit我們會(huì )得到很多的支持?;貧w測試就是你不斷地對所編寫(xiě)的代碼進(jìn)行測試:編寫(xiě)一些,測試一些,調試一些,然后循環(huán)這一過(guò)程,你會(huì )不斷地重復先前的測試,哪怕你正編寫(xiě)其他的類(lèi),由于軟件熵的存在,你可能在編寫(xiě)第五個(gè)類(lèi)的時(shí)候發(fā)現,第五個(gè)類(lèi)的某個(gè)操作會(huì )導致第二個(gè)類(lèi)的測試失敗。通過(guò)回歸測試我們抓住了這條大Bug。


回歸測試框架-JUnit
通過(guò)前面的介紹,我們對JUnit有了一個(gè)大概的輪廓。知道了它是干什么的?,F在讓我們動(dòng)手改寫(xiě)上面的測試類(lèi)testCar使其符合Junit的規范--能在JUnit中運行。

//執行測試的類(lèi)(JUnit版)
import junit.framework.*;

public class testCar extends TestCase {

protected int expectedWheels;
protected Car myCar;

public testCar(String name) {
super(name);
}

protected void setUp() {
expectedWheels = 4;
myCar = new Car();
}

public static Test suite() {
/*
 * the type safe way
 *
TestSuite suite= new TestSuite();
suite.addTest(
new testCar("Car.getWheels") {
 protected void runTest() { testGetWheels(); }
}
);
return suite;
*/

/*
 * the dynamic way
 */
return new TestSuite(testCar.class);
}

public void testGetWheels() {
assertEquals(expectedWheels, myCar.getWheels());
}
}

改版后的testCar已經(jīng)面目全非。先讓我們了解這些改動(dòng)都是什么含義,再看如何執行這個(gè)測試。

1>;import語(yǔ)句,引入JUnit的類(lèi)。(沒(méi)問(wèn)題吧)

2>;繼承 TestCase ??梢詴簳r(shí)將一個(gè)TestCase看作是對某個(gè)類(lèi)進(jìn)行測試的方法的集合。詳細介紹請參看JUnit資料

3>;setUp()設定了進(jìn)行初始化的任務(wù)。我們以后會(huì )看到setUp會(huì )有特別的用處。

4>;testGetWheeels()對預期的值和myCar.getWheels()返回的值進(jìn)行比較,并打印比較的結果。assertEquals是junit.framework.Assert中所定義的方法,junit.framework.TestCase繼承了junit.framework.Assert。

5>;suite()是一個(gè)很特殊的靜態(tài)方法。JUnit的TestRunner會(huì )調用suite方法來(lái)確定有多少個(gè)測試可以執行。上面的例子顯示了兩種方法:靜態(tài)的方法是構造一個(gè)內部類(lèi),并利用構造函數給該測試命名(test name, 如 Car.getWheels ),其覆蓋的runTest()方法,指明了該測試需要執行那些方法--testGetWheels()。動(dòng)態(tài)的方法是利用內?。╮eflection )來(lái)實(shí)現runTest(),找出需要執行那些測試。此時(shí)測試的名字即是測試方法(test method,如testGetWheels)的名字。JUnit會(huì )自動(dòng)找出并調用該類(lèi)的測試方法。

6>;將TestSuite看作是包裹測試的一個(gè)容器。如果將測試比作葉子節點(diǎn)的話(huà),TestSuite就是分支節點(diǎn)。實(shí)際上TestCase,TestSuite以及TestSuite組成了一個(gè)composite Pattern。 JUnit的文檔中有一篇專(zhuān)門(mén)講解如何使用Pattern構造Junit框架。有興趣的朋友可以查看JUnit資料。

如何運行該測試呢?手工的方法是鍵入如下命令:

[Windows] d:>;java junit.textui.TestRunner testCar 
   [Unix] % java junit.textui.TestRunner testCar

別擔心你要敲的字符量,以后在IDE中,只要點(diǎn)幾下鼠標就成了。運行結果應該如下所示,表明執行了一個(gè)測試,并通過(guò)了測試:

.
Time: 0

OK (1 tests)

如果我們將Car.getWheels()中返回的的值修改為3,模擬出錯的情形,則會(huì )得到如下結果: 
.F
Time: 0
There was 1 failure:
1) testGetWheels(testCar)junit.framework.AssertionFailedError: expected:<4>; but was:<3>;
at testCar.testGetWheels(testCar.java:37)

FAILURES!!!
Tests run: 1,  Failures: 1,  Errors: 0

注意:Time上的小點(diǎn)表示測試個(gè)數,如果測試通過(guò)則顯示OK。否則在小點(diǎn)的后邊標上F,表示該測試失敗。注意,在模擬出錯的測試中,我們會(huì )得到詳細的測試報告“expected:<4>; but was:<3>;”,這足以告訴我們問(wèn)題發(fā)生在何處。下面就是你調試,測試,調試,測試...的過(guò)程,直至得到期望的結果。


Design by Contract(這句話(huà)我沒(méi)法翻譯)

Design by Contract本是Bertrand Meyer(Eiffel語(yǔ)言的創(chuàng )始人)開(kāi)發(fā)的一種設計技術(shù)。我發(fā)現在JUnit中使用Design by Contract會(huì )帶來(lái)意想不到的效果。Design by Contract的核心是斷言(assersion)。斷言是一個(gè)布爾語(yǔ)句,該語(yǔ)句不能為假,如果為假,則表明出現了一個(gè)bug。Design by Contract使用三種斷言:前置條件(pre-conditions)、后置條件(post-conditions)和不變式(invariants)這里不打算詳細討論Design by Contract的細節,而是希望其在測試中能發(fā)揮其作用。

前置條件在執行測試之前可以用于判斷是否允許進(jìn)入測試,即進(jìn)入測試的條件。如 expectedWheels >; 0, myCar != null。后置條件用于在測試執行后判斷測試的結果是否正確。如 expectedWheels==myCar.getWheels()。而不變式在判斷交易(Transaction)的一致性(consistency)方面尤為有用。我希望JUnit可以將Design by Contract作為未來(lái)版本的一個(gè)增強。


Refactoring(這句話(huà)我依然沒(méi)法翻譯)

Refactoring本來(lái)與測試沒(méi)有直接的聯(lián)系,而是與軟件熵有關(guān),但既然我們說(shuō)測試能解決軟件熵問(wèn)題,我們也就必須說(shuō)出解決之道。(僅僅進(jìn)行測試只能發(fā)現軟件熵,Refactoring則可解決軟件熵帶來(lái)的問(wèn)題。)軟件熵引出了一個(gè)問(wèn)題:是否需要重新設計整個(gè)軟件的結構?理論上應該如此,但現實(shí)不允許我們這么做。這或者是由于時(shí)間的原因,或者是由于費用的原因。重新設計整個(gè)軟件的結構會(huì )給我們帶來(lái)短期的痛苦。而不停地給軟件打補丁甚至是補丁的補丁則會(huì )給我們帶來(lái)長(cháng)期的痛苦。(不管怎樣,我們總處于水深火熱之中)

Refactoring是一個(gè)術(shù)語(yǔ),用于描述一種技術(shù),利用這種技術(shù)我們可以免于重構整個(gè)軟件所帶來(lái)的短期痛苦。當你refactor時(shí),你并不改變程序的功能,而是改變程序內部的結構,使其更易理解和使用。如:該變一個(gè)方法的名字,將一個(gè)成員變量從一個(gè)類(lèi)移到另一個(gè)類(lèi),將兩個(gè)類(lèi)似方法抽象到父類(lèi)中。所作的每一個(gè)步都很小,然而1-2個(gè)小時(shí)的Refactoring工作可以使你的程序結構更適合目前的情況。Refactoring有一些規則:

1>; 不要在加入新功能的同時(shí)refactor已有的代碼。在這兩者間要有一個(gè)清晰的界限。如每天早上1-2個(gè)小時(shí)的Refactoring,其余時(shí)間添加新的功能。

2>; 在你開(kāi)始Refactoring前,和Refactoring后都要保證測試能順利通過(guò)。否則Refactoring沒(méi)有任何意義。

3>; 進(jìn)行小的Refactoring,大的就不是Refactoring了。如果你打算重構整個(gè)軟件,就沒(méi)有必要Refactoring了。

只有在添加新功能和調試bug時(shí)才又必要Refactoring。不要等到交付軟件的最后關(guān)頭才Refactoring。那樣和打補丁的區別不大。Refactoring 用在回歸測試中也能顯示其威力。要明白,我不反對打補丁,但要記住打補丁是應該最后使用的必殺絕招。(打補丁也需要很高的技術(shù),詳情參看微軟網(wǎng)站)


IDE對JUnit的支持

目前支持JUnit的Java IDE 包括 IDE 方式 個(gè)人評價(jià)(1-5,滿(mǎn)分5) 
Forte for Java 3.0 Enterprise Edition plug-in 3 
JBuilder 6 Enterprise Edition integrated with IDE 4 
Visual Age for Java  support N/A 

在IDE中如何使用JUnit,是非常具體的事情。不同的IDE有不同的使用方法。一旦理解了JUnit的本質(zhì),使用起來(lái)就十分容易了。所以我們不依賴(lài)于具體的IDE,而是集中精力講述如何利用JUnit編寫(xiě)單元測試代碼。心急的人可參看資料。


JUnit簡(jiǎn)介

既然我們已經(jīng)對JUnit有了一個(gè)大致的了解,我希望能給大家提供一個(gè)稍微正式一些的編寫(xiě)JUnit測試文檔的手冊,明白其中的一些關(guān)鍵術(shù)語(yǔ)和概念。但我要聲明的是這并不是一本完全的手冊,只能認為是一本入門(mén)手冊。同其他OpenSource的軟件有同樣的問(wèn)題,JUnit的文檔并沒(méi)有商業(yè)軟件文檔的那種有規則,簡(jiǎn)潔和完全。由開(kāi)發(fā)人員編寫(xiě)的文檔總是說(shuō)不太清楚問(wèn)題,全整的文檔需要參考"官方"指南,API手冊,郵件討論組的郵件,甚至包括源代碼中及相關(guān)的注釋。

事實(shí)上問(wèn)題并沒(méi)有那么復雜,除非你有非常特別的要求,否則,只需參考本文你就可以得到所需的大部分信息。


安裝

首先你要獲取JUnit的軟件包,從JUnit下載最新的軟件包(截至寫(xiě)作本文時(shí),JUnit的最新版本是3.7)。將其在適當的目錄下解包。這樣在安裝目錄(也就是你所選擇的解包的目錄)下你找到一個(gè)名為junit.jar的文件。將這個(gè)jar文件加入你的CLASSPATH系統變量。(IDE的設置會(huì )有所不同,參看你所喜愛(ài)的IDE的配置指南)JUnit就安裝完了。太easy了!

你一旦安裝完JUnit,就有可能想試試我們的Car和testCar類(lèi),沒(méi)問(wèn)題,我已經(jīng)運行過(guò)了,你得到的結果應該和我列出的結果類(lèi)似。(以防新版JUnit使我的文章過(guò)時(shí))

接下來(lái),你可能會(huì )先寫(xiě)測試代碼,再寫(xiě)工作代碼,或者相反,先寫(xiě)工作代碼,再寫(xiě)測試代碼。我更贊成使用前一種方法:先寫(xiě)測試代碼,再寫(xiě)工作代碼。因為這樣可以使我們編寫(xiě)工作代碼時(shí)清晰地了解工作類(lèi)的行為。

要注意編寫(xiě)一定能通過(guò)的測試代碼(如文中的例子)并沒(méi)有任何意義,只有測試代碼能幫助我們發(fā)現bug,測試代碼才有其價(jià)值。此外測試代碼還應該對工作代碼進(jìn)行全面的測試。如給方法調用的參數傳入空值、錯誤值和正確的值,看看方法的行為是否如你所期望的那樣。

你現在已經(jīng)知道了編寫(xiě)測試類(lèi)的基本步驟:
1>;擴展TestCase類(lèi);
2>;覆蓋runTest()方法(可選);
3>;寫(xiě)一些testXXXXX()方法;


Fixture

解下來(lái)的問(wèn)題是,如果你要對一個(gè)或若干個(gè)的類(lèi)執行多個(gè)測試,該怎么辦?JUnit對此有特殊的解決辦法。

如果需要在一個(gè)或若干個(gè)的類(lèi)執行多個(gè)測試,這些類(lèi)就成為了測試的context。在JUnit中被稱(chēng)為Fixture(如testCar類(lèi)中的 myCar 和 expectedWheels )。當你編寫(xiě)測試代碼時(shí),你會(huì )發(fā)現你花費了很多時(shí)間配置/初始化相關(guān)測試的Fixture。將配置Fixture的代碼放入測試類(lèi)的構造方法中并不可取,因為我們要求執行多個(gè)測試,我并不希望某個(gè)測試的結果意外地(如果這是你要求的,那就另當別論了)影響其他測試的結果。通常若干個(gè)測試會(huì )使用相同的Fixture,而每個(gè)測試又各有自己需要改變的地方。

為此,JUnit提供了兩個(gè)方法,定義在TestCase類(lèi)中。

protected void setUp() throws java.lang.Exception
protected void tearDown() throws java.lang.Exception

覆蓋setUp()方法,初始化所有測試的Fixture(你甚至可以在setUp中建立網(wǎng)絡(luò )連接),將每個(gè)測試略有不同的地方在testXXX()方法中進(jìn)行配置。

覆蓋tearDown()(我總想起一首叫雨滴的吉他曲),釋放你在setUp()中分配的永久性資源,如數據庫連接。

當JUnit執行測試時(shí),它在執行每個(gè)testXXXXX()方法前都調用setUp(),而在執行每個(gè)testXXXXX()方法后都調用tearDown()方法,由此保證了測試不會(huì )相互影響。


TestCase

需要提醒一下,在junit.framework.Assert類(lèi)中定義了相當多的assert方法,主要有assert(), assert(), assertEquals(), assertNull(), assertSame(), assertTrue(), fail()等方法。如果你需要比較自己定義的類(lèi),如Car。assert方法需要你覆蓋Object類(lèi)的equals()方法,以比較兩個(gè)對象的不同。實(shí)踐表明:如果你覆蓋了Object類(lèi)的equals()方法,最好也覆蓋Object類(lèi)的hashCode()方法。再進(jìn)一步,連帶Object類(lèi)的toString()方法也一并覆蓋。這樣可以使測試結果更具可讀性。

當你設置好了Fixture后,下一步是編寫(xiě)所需的testXXX()方法。一定要保證testXXX()方法的public屬性,否則無(wú)法通過(guò)內?。╮eflection)對該測試進(jìn)行調用。

每個(gè)擴展的TestCase類(lèi)(也就是你編寫(xiě)的測試類(lèi))會(huì )有多個(gè)testXXX()方法。一個(gè)testXXX()方法就是一個(gè)測試。要想運行這個(gè)測試,你必須定義如何運行該測試。如果你有多個(gè)testXXX()方法,你就要定義多次。JUnit支持兩種運行單個(gè)測試的方法:靜態(tài)的和動(dòng)態(tài)的方法。

靜態(tài)的方法就是覆蓋TestCase類(lèi)的runTest()方法,一般是采用內部類(lèi)的方式創(chuàng )建一個(gè)測試實(shí)例: 
TestCase test01 = new testCar("test getWheels") {
public void runTest() {
testGetWheels();
}
}

采用靜態(tài)的方法要注意要給每個(gè)測試一個(gè)名字(這個(gè)名字可以任意起,但你肯定希望這個(gè)名字有某種意義),這樣你就可以區分那個(gè)測試失敗了。

動(dòng)態(tài)的方法是用內省來(lái)實(shí)現runTest()以創(chuàng )建一個(gè)測試實(shí)例。這要求測試的名字就是需要調用的測試方法的名字: 
TestCase test01 = new testCar("testGetWheels");

JUnit會(huì )動(dòng)態(tài)查找并調用指定的測試方法。動(dòng)態(tài)的方法很簡(jiǎn)潔,但如果你鍵入了錯誤的名字就會(huì )得到一個(gè)令人奇怪的NoSuchMethodException異常。動(dòng)態(tài)的方法和靜態(tài)的方法都很好,你可以按照自己的喜好來(lái)選擇。(先別著(zhù)急選擇,后面還有一種更酷的方法等著(zhù)你呢。)


TestSuite

一旦你創(chuàng )建了一些測試實(shí)例,下一步就是要讓他們能一起運行。我們必須定義一個(gè)TestSuite。在JUnit中,這就要求你在TestCase類(lèi)中定義一個(gè)靜態(tài)的suite()方法。suite()方法就像main()方法一樣,JUnit用它來(lái)執行測試。在suite()方法中,你將測試實(shí)例加到一個(gè)TestSuite對象中,并返回這個(gè)TestSuite對象。一個(gè)TestSuite對象可以運行一組測試。TestSuite和TestCase都實(shí)現了Test接口(interface),而Test接口定義了運行測試所需的方法。這就允許你用TestCase和TestSuite的組合創(chuàng )建一個(gè)TestSuite。這就是為什么我們前面說(shuō)TestCase,TestSuite以及TestSuite組成了一個(gè)composite Pattern的原因。例子如下: 
public static Test suite() {
TestSuite suite= new TestSuite();
suite.addTest(new testCar("testGetWheels"));
suite.addTest(new testCar("testGetSeats"));
return suite;
}

從JUnit 2.0開(kāi)始,有一種更簡(jiǎn)單的動(dòng)態(tài)定義測試實(shí)例的方法。你只需將類(lèi)傳遞給TestSuite,JUnit會(huì )根據測試方法名自動(dòng)創(chuàng )建相應的測試實(shí)例。所以你的測試方法最好取名為testXXX()。例子如下: 
public static Test suite() {
return new TestSuite(testCar.class);
}

從JUnit的設計我們可看出,JUnit不僅可用于單元測試,也可用于集成測試。關(guān)于如何用JUnit進(jìn)行集成測試請參考相關(guān)資料。

為了兼容性的考慮,下面列出使用靜態(tài)方法的例子: 
public static Test suite() {
TestSuite suite= new TestSuite();
suite.addTest(
new testCar("getWheels") {
 protected void runTest() { testGetWheels(); }
}
);

suite.addTest(
new testCar("getSeats") {
 protected void runTest() { testGetSeats(); }
}
);
return suite;
}

TestRunner

有了TestSuite我們就可以運行這些測試了,JUnit提供了三種界面來(lái)運行測試 
[Text  UI] junit.textui.TestRunner
[AWT   UI] junit.awtui.TestRunner
[Swing UI] junit.swingui.TestRunner

我們前面已經(jīng)看過(guò)文本界面了,下面讓我們來(lái)看一看圖形界面:

 

界面很簡(jiǎn)單,鍵入類(lèi)名-testCar?;蛟趩?dòng)UI的時(shí)候鍵入類(lèi)名: 
[Windows] d:>;java junit.swingui.TestRunner testCar 
   [Unix] % java junit.swingui.TestRunner testCar

從圖形UI可以更好的運行測試可查單測試結果。還有一個(gè)問(wèn)題需要注意:如果JUnit報告了測試沒(méi)有成功,JUnit會(huì )區分失?。╢ailures)和錯誤(errors)。失敗是一個(gè)期望的被assert方法檢查到的結果。而錯誤則是意外的問(wèn)題引起的,如ArrayIndexOutOfBoundsException。

由于TestRunner十分簡(jiǎn)單,界面也比較直觀(guān),故不多介紹。朋友們可自行參考相關(guān)資料。


JUnit最佳實(shí)踐 

Martin Fowler(又是這位高人)說(shuō)過(guò):“當你試圖打印輸出一些信息或調試一個(gè)表達式時(shí),寫(xiě)一些測試代碼來(lái)替代那些傳統的方法。”一開(kāi)始,你會(huì )發(fā)現你總是要創(chuàng )建一些新的Fixture,而且測試似乎使你的編程速度慢了下來(lái)。然而不久之后,你會(huì )發(fā)現你重復使用相同的Fixture,而且新的測試通常只涉及添加一個(gè)新的測試方法。

你可能會(huì )寫(xiě)許多測試代碼,但你很快就會(huì )發(fā)現你設想出的測試只有一小部分是真正有用的。你所需要的測試是那些會(huì )失敗的測試,即那些你認為不會(huì )失敗的測試,或你認為應該失敗卻成功的測試。

我們前面提到過(guò)測試是一個(gè)不會(huì )中斷的過(guò)程。一旦你有了一個(gè)測試,你就要一直確保其正常工作,以檢驗你所加入的新的工作代碼。不要每隔幾天或最后才運行測試,每天你都應該運行一下測試代碼。這種投資很小,但可以確保你得到可以信賴(lài)的工作代碼。你的返工率降低了,你會(huì )有更多的時(shí)間編寫(xiě)工作代碼。

不要認為壓力大,就不寫(xiě)測試代碼。相反編寫(xiě)測試代碼會(huì )使你的壓力逐漸減輕,應為通過(guò)編寫(xiě)測試代碼,你對類(lèi)的行為有了確切的認識。你會(huì )更快地編寫(xiě)出有效率地工作代碼。下面是一些具體的編寫(xiě)測試代碼的技巧或較好的實(shí)踐方法:

1. 不要用TestCase的構造函數初始化Fixture,而要用setUp()和tearDown()方法。
2. 不要依賴(lài)或假定測試運行的順序,因為JUnit利用Vector保存測試方法。所以不同的平臺會(huì )按不同的順序從Vector中取出測試方法。
3. 避免編寫(xiě)有副作用的TestCase。例如:如果隨后的測試依賴(lài)于某些特定的交易數據,就不要提交交易數據。簡(jiǎn)單的會(huì )滾就可以了。
4. 當繼承一個(gè)測試類(lèi)時(shí),記得調用父類(lèi)的setUp()和tearDown()方法。
5. 將測試代碼和工作代碼放在一起,一邊同步編譯和更新。(使用Ant中有支持junit的task.)
6. 測試類(lèi)和測試方法應該有一致的命名方案。如在工作類(lèi)名前加上test從而形成測試類(lèi)名。
7. 確保測試與時(shí)間無(wú)關(guān),不要依賴(lài)使用過(guò)期的數據進(jìn)行測試。導致在隨后的維護過(guò)程中很難重現測試。
8. 如果你編寫(xiě)的軟件面向國際市場(chǎng),編寫(xiě)測試時(shí)要考慮國際化的因素。不要僅用母語(yǔ)的Locale進(jìn)行測試。
9. 盡可能地利用JUnit提供地assert/fail方法以及異常處理的方法,可以使代碼更為簡(jiǎn)潔。
10.測試要盡可能地小,執行速度快。

事實(shí)上,JUnit還可用于集成測試,但我并沒(méi)涉及到,原因有兩個(gè):一是因為沒(méi)有單元測試,集成測試無(wú)從談起。我們接受測試地概念已經(jīng)很不容易了,如果再引入集成測試就會(huì )更困難。二是我比較懶,希望將集成測試的任務(wù)交給測試人員去做。在JUnit的網(wǎng)站上有一些相關(guān)的文章,有空大家可以翻一翻。


JUnit與J2EE 

如果大家仔細考慮一下的話(huà),就會(huì )發(fā)現,JUnit有自己的局限性,比如對圖形界面的測試,對servlet/JSP以及EJB的測試我們都沒(méi)有舉相關(guān)的例子。實(shí)際上,JUnit對于GUI界面,servlet/JSP,JavaBean以及EJB都有辦法測試。關(guān)于GUI的測試比較復雜,適合用一整篇文章來(lái)介紹。這里就不多說(shuō)了。

前面我們所做的測試實(shí)際上有一個(gè)隱含的環(huán)境,JVM我們的類(lèi)需要這個(gè)JVM來(lái)執行。而在J2EE框架中,servlet/JSP,EJB都要求有自己的運行環(huán)境:Web Container和EJB Container。所以,要想對servlet/JSP,EJB進(jìn)行測試就需要將其部署在相應的Container中才能進(jìn)行測試。由于EJB不涉及UI的問(wèn)題(除非EJB操作XML數據,此時(shí)的測試代碼比較難寫(xiě),有可能需要你比較兩棵DOM樹(shù)是否含有相同的內容)只要部署上去之后就可以運行測試代碼了。此時(shí)setUp()方法顯得特別有用,你可以在setUp()方法中利用JNDI查找特定的EJB。而在testXXX()方法中調用并測試這些EJB的方法。

這里所指的JavaBean同樣沒(méi)有UI的問(wèn)題,比如,我們用JavaBean來(lái)訪(fǎng)問(wèn)數據庫,或用JavaBean來(lái)包裹EJB。如果這類(lèi)JavaBean沒(méi)有用到Container的提供的服務(wù),則可直接進(jìn)行測試,同我們前面所說(shuō)的一般的類(lèi)的測試方法一樣。如果這類(lèi)JavaBean用到了Container的提供的服務(wù),則需要將其部署在Container中才能進(jìn)行測試。方法與EJB類(lèi)似。

對于servlet/JSP的測試則比較棘手,有人建議在測試代碼中構造HttpRequest和HttpResponse,然后進(jìn)行比較,這就要求開(kāi)發(fā)人員對HTTP協(xié)議以及servlet/JSP的內部實(shí)現有比較深的認識。我認為這招不太現實(shí)。也有人提出使用HttpUnit。由于我對Cactus和HttpUnit 了解不多,所以無(wú)法做出合適的建議。希望各位先知們能不吝賜教。

正是由于JUnit的開(kāi)放性和簡(jiǎn)單易行,才會(huì )引出這篇介紹文章。但技術(shù)總在不斷地更新,而且我對測試并沒(méi)有非常深入的理解;我可以將一個(gè)復雜的概念簡(jiǎn)化成一句非常容易理解的話(huà)。但我的本意只是希望能降低開(kāi)發(fā)人員步入測試領(lǐng)域的門(mén)檻,而不是要修改或重新定義一些概念。這一點(diǎn)是特別要強調的。最后,如果有些兄弟姐妹能給我指出一些注意事項或我對某些問(wèn)題的理解有誤,我會(huì )非常感激的。
本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
JUnit入門(mén)
Junit使用簡(jiǎn)明手冊
netbeans 中使用Junit
java單元測試(使用junit)
Java單元測試(Junit+Mock+代碼覆蓋率)
Python 自動(dòng)單元測試框架
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久