您的位置:軟件測(cè)試 > 開(kāi)源軟件測(cè)試 > 開(kāi)源單元測(cè)試工具 > junit
全面認(rèn)識(shí)JUnit 4的特征
作者:網(wǎng)絡(luò)轉(zhuǎn)載 發(fā)布時(shí)間:[ 2013/1/4 15:58:25 ] 推薦標(biāo)簽:

  十、 高級(jí)測(cè)試

  現(xiàn)在,我將展示JUnit 4的一些高級(jí)特征。列表1(見(jiàn)下載源碼)是一個(gè)新的測(cè)試類(lèi)-AdvancedTest,它派生自AbstractParent。

  (一) 高級(jí)預(yù)設(shè)環(huán)境

  兩個(gè)類(lèi)都使用新的注解@BeforeClass和@AfterClass,還有@Before和@After。表格2展示了在這些注解之間的主要區(qū)別。

  表格2.@BeforeClass/@AfterClass比較于@Before/@After。

@BeforeClass和@AfterClass  @Before和@After
在每個(gè)類(lèi)中只有一個(gè)方法能被注解。  多個(gè)方法能被注解,但其執(zhí)行的順序未特別指定,且不運(yùn)行重載方法。
方法名是不相關(guān)的  方法名是不相關(guān)的
每個(gè)類(lèi)運(yùn)行一次  在每個(gè)測(cè)試方法運(yùn)行前或運(yùn)行后運(yùn)行
在當(dāng)前類(lèi)的@BeforeClass方法運(yùn)行前先運(yùn)行超類(lèi)的@BeforeClass方法。在超類(lèi)中聲明的@AfterClass方法將在所有當(dāng)前類(lèi)的該方法運(yùn)行后才運(yùn)行。  超類(lèi)中的@Before在所有子類(lèi)的該方法運(yùn)行前運(yùn)行。在超類(lèi)中的@After在在所有子類(lèi)的該方法運(yùn)行后才運(yùn)行。
必須是公共和非靜態(tài)的。  必須是公共和非靜態(tài)的。
即使一個(gè)@BeforeClass方法拋出一個(gè)異常,所有的@AfterClass方法也保證被運(yùn)行。  即使一個(gè)@Before或者@Test方法拋出一個(gè)異常,所有的@After方法也保證被運(yùn)行。

  如果你僅有一次需要分配和釋放昂貴的資源,那么@BeforeClass和@AfterClass可能很有用。在我們的例子中,AbstractParent使用這些在startTestSystem()和stopTestSystem()方法上的注解啟動(dòng)和停止整個(gè)測(cè)試系統(tǒng)。并且它使用@Before和@After初始化和清除系統(tǒng)。子類(lèi)AdvancedTest也混合使用這些注解。

  在你的測(cè)試代碼中使用System.out.println不是一種良好的實(shí)踐習(xí)慣;但是,在這個(gè)用例中,它有助于理解這些注解被調(diào)用的順序。當(dāng)我運(yùn)行AdvancedTest時(shí),我得到如下結(jié)果:

Start test system //父類(lèi)的@BeforeClass
Switch on calculator //子類(lèi)的@BeforeClass

Initialize test system //第一個(gè)測(cè)試
Clear calculator

Initialize test system //第二個(gè)測(cè)試
Clear calculator
Clean test system

Initialize test system //第三個(gè)測(cè)試
Clear calculator
Clean test system

Initialize test system //第四個(gè)測(cè)試
Clear calculator
Clean test system

Switch off calculator //子類(lèi)的@AfterClass
Stop test system //父類(lèi)的@AfterClass

  如你所見(jiàn),@BeforeClass和@AfterClass僅被調(diào)用一次,而@Before和@Afterare在每次測(cè)試中都要調(diào)用。

  (二) 測(cè)試

  在前面的例子中,我為squareRoot()方法編寫(xiě)了一個(gè)測(cè)試用例。記住,在這個(gè)方法中存在一個(gè)錯(cuò)誤-能夠?qū)е滤鼰o(wú)限循環(huán)。如果沒(méi)有結(jié)果的話(huà),我想讓這個(gè)測(cè)試在1秒鐘后退出。這一功能正是timeout參數(shù)所要實(shí)現(xiàn)的。@Test注解的第二個(gè)可選參數(shù)(第一個(gè)參數(shù)是必需的)可以使一個(gè)測(cè)試失敗,如果該測(cè)試花費(fèi)比一個(gè)預(yù)先確定的時(shí)限(毫秒)還長(zhǎng)的時(shí)間的話(huà)。當(dāng)我運(yùn)行該測(cè)試時(shí),我得到如下的運(yùn)行結(jié)果:

There was 1 failure:

1) squareRoot(JUnit 4.AdvancedTest)
java.lang.Exception: test timed out after 1000 milliseconds
at org.junit.internal.runners.TestMethodRunner.runWithTimeout(TestMethodRunner.java:68)
at org.junit.internal.runners.TestMethodRunner.運(yùn)行(TestMethodRunner.java:43)

FAILURES!!!
Tests run: 4, Failures: 1

  (三) 參數(shù)化測(cè)試

  在列表1中,我測(cè)試了squareRoot(它是square方法而不是squareRoot方法)-通過(guò)創(chuàng)建若干測(cè)試方法(square2,square4,square5),這些方法都完成相同的事情(通過(guò)被一些變量參數(shù)化實(shí)現(xiàn))。其實(shí),現(xiàn)在這里的復(fù)制/粘貼技術(shù)可以通過(guò)使用一個(gè)參數(shù)化測(cè)試用例加以?xún)?yōu)化(列表2)。

  在列表2(見(jiàn)本文相應(yīng)下載源碼)中的測(cè)試用例使用了兩個(gè)新的注解。當(dāng)一個(gè)類(lèi)被使用@RunWith注釋時(shí),JUnit將調(diào)用被參考的類(lèi)來(lái)運(yùn)行該測(cè)試而不是使用缺省的運(yùn)行機(jī)。為了使用一個(gè)參數(shù)化測(cè)試用例,你需要使用運(yùn)行機(jī)org.junit.runners.Parameterized。為了確定使用哪個(gè)參數(shù),該測(cè)試用例需要一個(gè)公共靜態(tài)方法(在此是data(),但是名字似乎無(wú)關(guān)),該方法返回一個(gè)Collection,并且被使用@參數(shù)加以注解。你還需要一個(gè)使用這些參數(shù)的公共構(gòu)造函數(shù)。

  當(dāng)運(yùn)行這個(gè)類(lèi),該輸出是:

java org.junit.runner.JUnitCore JUnit 4.SquareTest
JUnit version 4.1

.......E

There was 1 failure:
1) square[6](JUnit 4.SquareTest)
java.lang.AssertionError: expected:<48> but was:<49>
at org.junit.Assert.fail(Assert.java:69)

FAILURES!!!
Tests run: 7, Failures: 1

  在此,共執(zhí)行了7個(gè)測(cè)試,好象編寫(xiě)了7個(gè)單獨(dú)的square方法。注意,在我們的測(cè)試中出現(xiàn)了一個(gè)失敗,因?yàn)?的平方是49,而不是48。

  (四) 測(cè)試集

  為了在JUnit 3.8的一個(gè)測(cè)試集中運(yùn)行若干測(cè)試類(lèi),你必須在你的類(lèi)中添加一個(gè)suite()方法。而在JUnit 4中,你可以使用注解來(lái)代之。為了運(yùn)行CalculatorTest和SquareTest,你需要使用@RunWith和@Suite注解編寫(xiě)一個(gè)空類(lèi)。

package JUnit 4;

import org.junit.runner.RunWith;
import org.junit.runners.Suite;

@RunWith(Suite.class)
@Suite.SuiteClasses({
CalculatorTest.class,
SquareTest.class
})
public class AllCalculatorTests {}

  在此,@RunWith注解告訴JUnit它使用org.junit.runner.Suite。這個(gè)運(yùn)行機(jī)允許你手工地構(gòu)建一個(gè)包含測(cè)試(可能來(lái)自許多類(lèi))的測(cè)試集。這些類(lèi)的名稱(chēng)都被定義在@Suite.SuiteClass中。當(dāng)你運(yùn)行這個(gè)類(lèi)時(shí),它將運(yùn)行CalculatorTest和SquareTest。其輸出是:

java -ea org.junit.runner.JUnitCore JUnit 4.AllCalculatorTests
JUnit version 4.1
...E.EI.......E
There were 3 failures:
1) subtract(JUnit 4.CalculatorTest)
java.lang.AssertionError: expected:<9> but was:<8>
at org.junit.Assert.fail(Assert.java:69)
2) divide(JUnit 4.CalculatorTest)
java.lang.AssertionError
at JUnit 4.CalculatorTest.divide(CalculatorTest.java:40)
3) square[6](JUnit 4.SquareTest)
java.lang.AssertionError: expected:<48> but was:<49>
at org.junit.Assert.fail(Assert.java:69)
FAILURES!!!
Tests run: 11, Failures: 3

  (五) 測(cè)試運(yùn)行機(jī)

  在JUnit 4中,廣泛地使用測(cè)試運(yùn)行機(jī)。如果沒(méi)有指定@RunWith,那么你的類(lèi)仍然會(huì)使用一個(gè)默認(rèn)運(yùn)行機(jī)(org.junit.internal.runners.TestClassRunner)執(zhí)行。注意,初的Calculator類(lèi)中并沒(méi)有顯式地聲明一個(gè)測(cè)試運(yùn)行機(jī);因此,它使用的是默認(rèn)運(yùn)行機(jī)。一個(gè)包含一個(gè)帶有@Test的方法的類(lèi)都隱含地?fù)碛幸粋(gè)@RunWith。事實(shí)上,你可以把下列代碼添加到Calculator類(lèi)上,而且其輸出結(jié)果會(huì)完全一樣。

import org.junit.internal.runners.TestClassRunner;
import org.junit.runner.RunWith;
@RunWith(TestClassRunner.class)
public class CalculatorTest {
...
}

  在@Parameterized和@Suite的情況下,我需要一個(gè)特定的運(yùn)行機(jī)來(lái)執(zhí)行我的測(cè)試用例。這是為什么我顯式地注解了它們。

上一頁(yè)12345下一頁(yè)
軟件測(cè)試工具 | 聯(lián)系我們 | 投訴建議 | 誠(chéng)聘英才 | 申請(qǐng)使用列表 | 網(wǎng)站地圖
滬ICP備07036474 2003-2017 版權(quán)所有 上海澤眾軟件科技有限公司 Shanghai ZeZhong Software Co.,Ltd