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

  十、 高級測試

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

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

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

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

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

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

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

Start test system //父類的@BeforeClass
Switch on calculator //子類的@BeforeClass

Initialize test system //第一個測試
Clear calculator

Initialize test system //第二個測試
Clear calculator
Clean test system

Initialize test system //第三個測試
Clear calculator
Clean test system

Initialize test system //第四個測試
Clear calculator
Clean test system

Switch off calculator //子類的@AfterClass
Stop test system //父類的@AfterClass

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

  (二) 測試

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

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

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

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

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個測試,好象編寫了7個單獨(dú)的square方法。注意,在我們的測試中出現(xiàn)了一個失敗,因?yàn)?的平方是49,而不是48。

  (四) 測試集

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

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。這個運(yùn)行機(jī)允許你手工地構(gòu)建一個包含測試(可能來自許多類)的測試集。這些類的名稱都被定義在@Suite.SuiteClass中。當(dāng)你運(yùn)行這個類時,它將運(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

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

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

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

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

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