日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

在Eclipse中使用JUnit4進行單元測試

系統(tǒng) 2479 0

我們在編寫大型程序的時候,需要寫成千上萬個方法或函數(shù),這些函數(shù)的功能可能很強大,但我們在程序中只用到該函數(shù)的一小部分功能,并且經(jīng)過調(diào)試可以確定,這 一小部分功能是正確的。但是,我們同時應(yīng)該確保每一個函數(shù)都完全正確,因為如果我們今后如果對程序進行擴展,用到了某個函數(shù)的其他功能,而這個功能有bug的話,那絕對是一件非常郁悶的事情。所以說,每編寫完一個函數(shù)之后,都應(yīng)該對這個函數(shù)的方方面面進行測試,這樣的測試我們稱之為單元測試。 傳統(tǒng)的編程方式,進行單元測試是一件很麻煩的事情,你要重新寫另外一個程序,在該程序中調(diào)用你需要測試的方法,并且仔細觀察運行結(jié)果,看看是否有錯。正因 為如此麻煩,所以程序員們編寫單元測試的熱情不是很高。于是有一個牛人推出了單元測試包,大大簡化了進行單元測試所要做的工作,這就是JUnit4。本文簡要介紹一下在Eclipse3.2中使用JUnit4進行單元測試的方法。

  首先,我們來一個傻瓜式速成教程,不要問為什么,F(xiàn)ollow Me,先來體驗一下單元測試的快感!

  首先新建一個項目叫JUnit_Test,我們編寫一個Calculator類,這是一個能夠簡單實現(xiàn)加減乘除、平方、開方的計算器類,然后對這些功能進行單元測試。這個類并不是很完美,我們故意保留了一些Bug用于演示,這些Bug在注釋中都有說明。該類代碼如下:

  package andycpp;

  public class Calculator ...{

  private static int result; // 靜態(tài)變量,用于存儲運行結(jié)果

  public void add(int n) ...{

  result = result + n;

  }

  public void substract(int n) ...{

  result = result - 1; //Bug: 正確的應(yīng)該是 result =result-n

  }

  public void multiply(int n) ...{

  } // 此方法尚未寫好

  public void divide(int n) ...{

  result = result / n;

  }

  public void square(int n) ...{

  result = n * n;

  }

  public void squareRoot(int n) ...{

  for (; ;) ; //Bug : 死循環(huán)

  }

  public void clear() ...{ // 將結(jié)果清零

  result = 0;

  }

  public int getResult() ...{

  return result;

  }

  }

  第二步,將JUnit4單元測試包引入這個項目:在該項目上點右鍵,點“屬性”,如圖:

在Eclipse中使用JUnit4進行單元測試

  在彈出的屬性窗口中,首先在左邊選擇“Java Build Path”,然后到右上選擇“Libraries”標(biāo)簽,之后在最右邊點擊“Add Library…”按鈕,如下圖所示:

在Eclipse中使用JUnit4進行單元測試

  然后在新彈出的對話框中選擇JUnit4并點擊確定,如上圖所示,JUnit4軟件包就被包含進我們這個項目了。

wordend 相關(guān)閱讀:

  • Junit實現(xiàn)spring的單元測試
  • Junit多線程測試的一個解決方案
  • JUnit及其相關(guān)的單元測試技術(shù)

  第三步,生成JUnit測試框架:在Eclipse的Package Explorer中用右鍵點擊該類彈出菜單,選擇“JUnit 測試用例”。如下圖所示:

在Eclipse中使用JUnit4進行單元測試

  在彈出的對話框中,進行相應(yīng)的選擇,如下圖所示:

在Eclipse中使用JUnit4進行單元測試

  點擊“下一步”后,系統(tǒng)會自動列出你這個類中包含的方法,選擇你要進行測試的方法。此例中,我們僅對“加、減、乘、除”四個方法進行測試。如下圖所示:

在Eclipse中使用JUnit4進行單元測試

  之后系統(tǒng)會自動生成一個新類CalculatorTest,里面包含一些空的測試用例。你只需要將這些測試用例稍作修改即可使用。完整的CalculatorTest代碼如下:

  package andycpp;

  import static org.junit.Assert.*;

  import org.junit.Before;

  import org.junit.Ignore;

  import org.junit.Test;

  public class CalculatorTest ...{

  private static Calculator calculator = new Calculator();

  @Before

  public void setUp() throws Exception ...{

  calculator.clear();

  }

  @Test

  public void testAdd() ...{

  calculator.add(2);

  calculator.add(3);

  assertEquals(5, calculator.getResult());

  }

  @Test

  public void testSubstract() ...{

  calculator.add(10);

  calculator.substract(2);

  assertEquals(8, calculator.getResult());

  }

  @Ignore("Multiply() Not yet implemented")

  @Test

  public void testMultiply() ...{

  }

  @Test

  public void testDivide() ...{

  calculator.add(8);

  calculator.divide(2);

  assertEquals(4, calculator.getResult());

  }

  }

wordend 相關(guān)閱讀:

  • Junit實現(xiàn)spring的單元測試
  • Junit多線程測試的一個解決方案
  • JUnit及其相關(guān)的單元測試技術(shù)

  第四步,運行測試代碼:按照上述代碼修改完畢后,我們在CalculatorTest類上點右鍵,選擇“Run As à JUnit Test”來運行我們的測試,如下圖所示:

在Eclipse中使用JUnit4進行單元測試

  運行結(jié)果如下:

在Eclipse中使用JUnit4進行單元測試

  進度條是紅顏色表示發(fā)現(xiàn)錯誤,具體的測試結(jié)果在進度條上面有表示“共進行了4個測試,其中1個測試被忽略,一個測試失敗”。

  至此,我們已經(jīng)完整體驗了在Eclipse中使用JUnit的方法。在接下來的文章中,我會詳細解釋測試代碼中的每一個細節(jié)。

wordend 相關(guān)閱讀:

  • Junit實現(xiàn)spring的單元測試
  • Junit多線程測試的一個解決方案
  • JUnit及其相關(guān)的單元測試技術(shù)

  我們繼續(xù)對初級篇中的例子進行分析。初級篇中我們使用Eclipse自動生成了一個測試框架,在這篇文章中,我們來仔細分析一下這個測試框架中的每一個細節(jié),知其然更要知其所以然,才能更加熟練地應(yīng)用JUnit4。

  一、包含必要地Package

  在測試類中用到了JUnit4框架,自然要把相應(yīng)地Package包含進來。最主要地一個Package就是org.junit.*。把它包含進來之后,絕大部分功能就有了。還有一句話也非常地重要“import static org.junit.Assert.*;”,我們在測試的時候使用的一系列assertEquals方法就來自這個包。大家注意一下,這是一個靜態(tài)包含(static),是JDK5中新增添的一個功能。也就是說,assertEquals是Assert類中的一系列的靜態(tài)方法,一般的使用方式是 Assert. assertEquals(),但是使用了靜態(tài)包含后,前面的類名就可以省略了,使用起來更加的方便。

  二、測試類的聲明

  大家注意到,我們的測試類是一個獨立的類,沒有任何父類。測試類的名字也可以任意命名,沒有任何局限性。所以我們不能通過類的聲明來判斷它是不是一個測試類,它與普通類的區(qū)別在于它內(nèi)部的方法的聲明,我們接著會講到。

  三、創(chuàng)建一個待測試的對象

  你要測試哪個類,那么你首先就要創(chuàng)建一個該類的對象。正如上一篇文章中的代碼:

  private staticCalculator calculator =newCalculator();

  為了測試Calculator類,我們必須創(chuàng)建一個calculator對象。

  四、測試方法的聲明

  在測試類中,并不是每一個方法都是用于測試的,你必須使用“標(biāo)注”來明確表明哪些是測試方法。“標(biāo)注”也是JDK5的一個新特性,用在此處非常恰當(dāng)。我們可以看到,在某些方法的前有@Before、@Test、@Ignore等字樣,這些就是標(biāo)注,以一個“@”作為開頭。這些標(biāo)注都是JUnit4自定義的,熟練掌握這些標(biāo)注的含義非常重要。

  五、編寫一個簡單的測試方法

  首先,你要在方法的前面使用@Test標(biāo)注,以表明這是一個測試方法。對于方法的聲明也有如下要求:名字可以隨便取,沒有任何限制,但是返回值必須為 void,而且不能有任何參數(shù)。如果違反這些規(guī)定,會在運行時拋出一個異常。至于方法內(nèi)該寫些什么,那就要看你需要測試些什么了。比如:

  @Test

  public voidtestAdd() ...{

  calculator.add(2);

  calculator.add(3);

  assertEquals(5, calculator.getResult());

  }

  我們想測試一下“加法”功能時候正確,就在測試方法中調(diào)用幾次add函數(shù),初始值為0,先加2,再加3,我們期待的結(jié)果應(yīng)該是5。如果最終實際結(jié)果也是 5,則說明add方法是正確的,反之說明它是錯的。assertEquals(5, calculator.getResult());就是來判斷期待結(jié)果和實際結(jié)果是否相等,第一個參數(shù)填寫期待結(jié)果,第二個參數(shù)填寫實際結(jié)果,也就是通過計算得到的結(jié)果。這樣寫好之后,JUnit會自動進行測試并把測試結(jié)果反饋給用戶。

wordend 相關(guān)閱讀:

  • Junit實現(xiàn)spring的單元測試
  • Junit多線程測試的一個解決方案
  • JUnit及其相關(guān)的單元測試技術(shù)

  六、 忽略測試某些尚未完成的方法

  如果你在寫程序前做了很好的規(guī)劃,那么哪些方法是什么功能都應(yīng)該實現(xiàn)定下來。因此,即使該方法尚未完成,他的具體功能也是確定的,這也就意味著你可以為他編寫測試用例。但是,如果你已經(jīng)把該方法的測試用例寫完,但該方法尚未完成,那么測試的時候一定是“失敗”。這種失敗和真正的失敗是有區(qū)別的,因此JUnit 提供了一種方法來區(qū)別他們,那就是在這種測試函數(shù)的前面加上@Ignore標(biāo)注,這個標(biāo)注的含義就是“某些方法尚未完成,暫不參與此次測試”。這樣的話測試結(jié)果就會提示你有幾個測試被忽略,而不是失敗。一旦你完成了相應(yīng)函數(shù),只需要把@Ignore標(biāo)注刪去,就可以進行正常的測試。

  七、 Fixture(暫且翻譯為“固定代碼段”)

  Fixture 的含義就是“在某些階段必然被調(diào)用的代碼”。比如我們上面的測試,由于只聲明了一個Calculator對象,他的初始值是0,但是測試完加法操作后,他的值就不是0了;接下來測試減法操作,就必然要考慮上次加法操作的結(jié)果。這絕對是一個很糟糕的設(shè)計!我們非常希望每一個測試都是獨立的,相互之間沒有任何耦合度。因此,我們就很有必要在執(zhí)行每一個測試之前,對Calculator對象進行一個“復(fù)原”操作,以消除其他測試造成的影響。因此,“在任何一個測試執(zhí)行之前必須執(zhí)行的代碼”就是一個Fixture,我們用@Before來標(biāo)注它,如前面例子所示:

  @Before

  public void setUp() throws Exception ...{

  calculator.clear();

  }

  這里不在需要@Test標(biāo)注,因為這不是一個test,而是一個Fixture。同理,如果“在任何測試執(zhí)行之后需要進行的收尾工作”也是一個Fixture,使用@After來標(biāo)注。由于本例比較簡單,沒有用到此功能。

  JUnit4的一些基本知識就介紹到此,還有一些更靈活的用法放在本系列的高級篇中給大家介紹!

wordend 相關(guān)閱讀:

  • Junit實現(xiàn)spring的單元測試
  • Junit多線程測試的一個解決方案
  • JUnit及其相關(guān)的單元測試技術(shù)

  通過前兩篇文章,您一定對JUnit有了一個基本的了解,下面我們來探討一下JUnit4中一些高級特性。

  一、 高級Fixture

  上一篇文章中我們介紹了兩個Fixture標(biāo)注,分別是@Before和@After,我們來看看他們是否適合完成如下功能:有一個類是負責(zé)對大文件(超過 500兆)進行讀寫,他的每一個方法都是對文件進行操作。換句話說,在調(diào)用每一個方法之前,我們都要打開一個大文件并讀入文件內(nèi)容,這絕對是一個非常耗費時間的操作。如果我們使用@Before和@After,那么每次測試都要讀取一次文件,效率及其低下。這里我們所希望的是在所有測試一開始讀一次文件,所有測試結(jié)束之后釋放文件,而不是每次測試都讀文件。JUnit的作者顯然也考慮到了這個問題,它給出了@BeforeClass 和 @AfterClass兩個Fixture來幫我們實現(xiàn)這個功能。從名字上就可以看出,用這兩個Fixture標(biāo)注的函數(shù),只在測試用例初始化時執(zhí)行 @BeforeClass方法,當(dāng)所有測試執(zhí)行完畢之后,執(zhí)行@AfterClass進行收尾工作。在這里要注意一下,每個測試類只能有一個方法被標(biāo)注為 @BeforeClass 或 @AfterClass,并且該方法必須是Public和Static的。

  二、 限時測試

  還記得我在初級篇中給出的例子嗎,那個求平方根的函數(shù)有Bug,是個死循環(huán):

  public voidsquareRoot(intn) ...{

  for(; ;) ; //Bug : 死循環(huán)

  }

  如果測試的時候遇到死循環(huán),你的臉上絕對不會露出笑容。因此,對于那些邏輯很復(fù)雜,循環(huán)嵌套比較深的程序,很有可能出現(xiàn)死循環(huán),因此一定要采取一些預(yù)防措施。限時測試是一個很好的解決方案。我們給這些測試函數(shù)設(shè)定一個執(zhí)行時間,超過了這個時間,他們就會被系統(tǒng)強行終止,并且系統(tǒng)還會向你匯報該函數(shù)結(jié)束的原因是因為超時,這樣你就可以發(fā)現(xiàn)這些Bug了。要實現(xiàn)這一功能,只需要給@Test標(biāo)注加一個參數(shù)即可,代碼如下:

  @Test(timeout = 1000)

  public voidsquareRoot() ...{

  calculator.squareRoot(4);

  assertEquals(2, calculator.getResult());

  }

  Timeout參數(shù)表明了你要設(shè)定的時間,單位為毫秒,因此1000就代表1秒。

  三、 測試異常

  JAVA中的異常處理也是一個重點,因此你經(jīng)常會編寫一些需要拋出異常的函數(shù)。那么,如果你覺得一個函數(shù)應(yīng)該拋出異常,但是它沒拋出,這算不算Bug呢?這當(dāng)然是Bug,并 JUnit也考慮到了這一點,來幫助我們找到這種Bug。例如,我們寫的計算器類有除法功能,如果除數(shù)是一個0,那么必然要拋出“除0異常”。因此,我們很有必要對這些進行測試。代碼如下:

  @Test(expected = ArithmeticException.class)

  public void divideByZero() ...{

  calculator.divide(0);

  }

  如上述代碼所示,我們需要使用@Test標(biāo)注的expected屬性,將我們要檢驗的異常傳遞給他,這樣JUnit框架就能自動幫我們檢測是否拋出了我們指定的異常。

  四、 Runner (運行器)

  大家有沒有想過這個問題,當(dāng)你把測試代碼提交給JUnit框架后,框架如何來運行你的代碼呢?答案就是——Runner。在JUnit中有很多個 Runner,他們負責(zé)調(diào)用你的測試代碼,每一個Runner都有各自的特殊功能,你要根據(jù)需要選擇不同的Runner來運行你的測試代碼。可能你會覺得奇怪,前面我們寫了那么多測試,并沒有明確指定一個Runner啊?這是因為JUnit中有一個默認Runner,如果你沒有指定,那么系統(tǒng)自動使用默認Runner來運行你的代碼。換句話說,下面兩段代碼含義是完全一樣的:

  import org.junit.internal.runners.TestClassRunner;

  import org.junit.runner.RunWith;

  //使用了系統(tǒng)默認的TestClassRunner,與下面代碼完全一樣

  public class CalculatorTest ...{

  ...

  }

  @RunWith(TestClassRunner.class)

  public class CalculatorTest ...{

  ...

  }

  從上述例子可以看出,要想指定一個Runner,需要使用@RunWith標(biāo)注,并且把你所指定的Runner作為參數(shù)傳遞給它。另外一個要注意的是,@RunWith是用來修飾類的,而不是用來修飾函數(shù)的。只要對一個類指定了Runner,那么這個類中的所有函數(shù)都被這個Runner來調(diào)用。最后,不要忘了包含相應(yīng)的Package哦,上面的例子對這一點寫的很清楚了。接下來,我會向你們展示其他Runner的特有功能。

wordend 相關(guān)閱讀:

  • Junit實現(xiàn)spring的單元測試
  • Junit多線程測試的一個解決方案
  • JUnit及其相關(guān)的單元測試技術(shù)

  五、 參數(shù)化測試

  你可能遇到過這樣的函數(shù),它的參數(shù)有許多特殊值,或者說他的參數(shù)分為很多個區(qū)域。比如,一個對考試分數(shù)進行評價的函數(shù),返回值分別為“優(yōu)秀,良好,一般,及格,不及格”,因此你在編寫測試的時候,至少要寫5個測試,把這5中情況都包含了,這確實是一件很麻煩的事情。我們還使用我們先前的例子,測試一下“計算一個數(shù)的平方”這個函數(shù),暫且分三類:正數(shù)、0、負數(shù)。測試代碼如下:

  import org.junit.AfterClass;

  import org.junit.Before;

  import org.junit.BeforeClass;

  import org.junit.Test;

  import static org.junit.Assert.*;

  public class AdvancedTest ...{

  private static Calculator calculator = new Calculator();

  @Before

  public void clearCalculator() ...{

  calculator.clear();

  }

  @Test

  public void square1() ...{

  calculator.square(2);

  assertEquals(4, calculator.getResult());

  }

  @Test

  public void square2() ...{

  calculator.square(0);

  assertEquals(0, calculator.getResult());

  }

  @Test

  public void square3() ...{

  calculator.square(-3);

  assertEquals(9, calculator.getResult());

  }

  }

  為了簡化類似的測試,JUnit4提出了“參數(shù)化測試”的概念,只寫一個測試函數(shù),把這若干種情況作為參數(shù)傳遞進去,一次性的完成測試。代碼如下:

  import static org.junit.Assert.assertEquals;

  import org.junit.Test;

  import org.junit.runner.RunWith;

  import org.junit.runners.Parameterized;

  import org.junit.runners.Parameterized.Parameters;

  import java.util.Arrays;

  import java.util.Collection;

  @RunWith(Parameterized.class)

  public class SquareTest ...{

  private static Calculator calculator = new Calculator();

  private int param;

  private int result;

  @Parameters

  public static Collection data() ...{

  return Arrays.asList(new Object[][]...{

  ...{2, 4},

  ...{0, 0},

  ...{-3, 9},

  });

  }

  //構(gòu)造函數(shù),對變量進行初始化

wordend 相關(guān)閱讀:

  • Junit實現(xiàn)spring的單元測試
  • Junit多線程測試的一個解決方案
  • JUnit及其相關(guān)的單元測試技術(shù)

在Eclipse中使用JUnit4進行單元測試


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 藁城市| 德化县| 九龙城区| 阜阳市| 新田县| 巍山| 浮梁县| 调兵山市| 芜湖市| 桃园市| 黄陵县| 乌鲁木齐市| 瑞金市| 汾阳市| 玛曲县| 资源县| 都昌县| 泸溪县| 宁阳县| 通道| 江达县| 福建省| 洱源县| 泗洪县| 天等县| 准格尔旗| 辽宁省| 神农架林区| 全椒县| 化州市| 阜康市| 晋城| 铁岭县| 黑山县| 景谷| 叙永县| 江门市| 青阳县| 鲁甸县| 资源县| 伊金霍洛旗|