91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

java單元測試JUnit框架原理的示例分析

發布時間:2021-08-04 09:48:52 來源:億速云 閱讀:123 作者:小新 欄目:編程語言

小編給大家分享一下java單元測試JUnit框架原理的示例分析,希望大家閱讀完這篇文章之后都有所收獲,下面讓我們一起去探討吧!

具體如下:

1 簡介

JUnit是一個Java語言的單元測試框架,它由 Kent Beck 和 Erich Gamma 建立,逐漸成為 xUnit 家族中最為成功的一個。 JUnit有它自己的JUnit擴展生態圈,多數Java的開發環境都已經集成了JUnit作為單元測試的工具。在這里,一個單元可以是一個方法、類、包或者子系統。因此,單元測試是指對代碼中的最小可測試單元進行檢查和驗證,以便確保它們正常工作。例如,我們可以給予一定的輸入測試輸出是否是所希望得到的結果。

2 特點

JUnit提供了注釋以及確定的測試方法;
JUnit提供了斷言用于測試預期的結果;
JUnit測試優雅簡潔不需要花費太多的時間;
JUnit測試讓大家可以更快地編寫代碼并且提高質量;
JUnit測試可以組織成測試套件包含測試案例,甚至其他測試套件;
Junit顯示測試進度,如果測試是沒有問題條形是綠色的,測試失敗則會變成紅色;
JUnit測試可以自動運行,檢查自己的結果,并提供即時反饋,沒有必要通過測試結果報告來手動梳理。

3 內容

3.1 注解

@Test :該注釋表示,用其附著的公共無效方法(即用public修飾的void類型的方法 )可以作為一個測試用例;
@Before :該注釋表示,用其附著的方法必須在類中的每個測試之前執行,以便執行測試某些必要的先決條件;
@BeforeClass :該注釋表示,用其附著的靜態方法必須執行一次并在類的所有測試之前,發生這種情況時一般是測試計算共享配置方法,如連接到數據庫;
@After :該注釋表示,用其附著的方法在執行每項測試后執行,如執行每一個測試后重置某些變量,刪除臨時變量等;
@AfterClass :該注釋表示,當需要執行所有的測試在JUnit測試用例類后執行,AfterClass注解可以使用以清理建立方法,如斷開數據庫連接,注意:附有此批注(類似于BeforeClass)的方法必須定義為靜態;
@Ignore :該注釋表示,當想暫時禁用特定的測試執行可以使用忽略注釋,每個被注解為@Ignore的方法將不被執行。

/**
* JUnit 注解示例
*/
@Test
public void testYeepay(){
  Syetem.out.println("用@Test標示測試方法!");
}
@AfterClass
public static void paylus(){
  Syetem.out.println("用@AfterClass標示的方法在測試用例類執行完之后!");
}

3.2 斷言

在這里,作者將介紹一些斷言方法,所有這些方法都來自 org.junit.Assert 類,其擴展了 java.lang.Object 類并為它們提供編寫測試,以便檢測故障。簡而言之,我們就是通過斷言方法來判斷實際結果與我們預期的結果是否相同,如果相同,則測試成功,反之,則測試失敗。

void assertEquals([String message], expected value, actual value) :斷言兩個值相等,值的類型可以為int、short、long、byte、char 或者
java.lang.Object,其中第一個參數是一個可選的字符串消息;
void assertTrue([String message], boolean condition) :斷言一個條件為真;
void assertFalse([String message],boolean condition) :斷言一個條件為假;
void assertNotNull([String message], java.lang.Object object) :斷言一個對象不為空(null);
void assertNull([String message], java.lang.Object object) :斷言一個對象為空(null);
void assertSame([String message], java.lang.Object expected, java.lang.Object actual) :斷言兩個對象引用相同的對象;
void assertNotSame([String message], java.lang.Object unexpected, java.lang.Object actual) :斷言兩個對象不是引用同一個對象;
void assertArrayEquals([String message], expectedArray, resultArray) :斷言預期數組和結果數組相等,數組的類型可以為int、long、short、char、byte 或者 java.lang.Object

4 JUnit 3.X 和 JUnit 4.X 的區別

4.1 JUnit 3.X

(1)使用 JUnit 3.X 版本進行單元測試時,測試類必須要繼承于 TestCase 父類;
(2)測試方法需要遵循的原則:

① public的;
② void的;
③ 無方法參數;
④方法名稱必須以 test 開頭;

(3)不同的測試用例之間一定要保持完全的獨立性,不能有任何的關聯;
(4)要掌握好測試方法的順序,不能依賴于測試方法自己的執行順序。

/**
* 用 JUnit 3.X 進行測試
*/
import junit.framework.Assert;
import junit.framework.TestCase;
public class TestOperation extends TestCase {
  private Operation operation;
  public TestOperation(String name) { // 構造函數
    super(name);
  }
  @Override
  public void setUp() throws Exception { // 在每個測試方法執行 [之前] 都會被調用,多用于初始化
    System.out.println("歡迎使用Junit進行單元測試...");
    operation = new Operation();
  }
  @Override
  public void tearDown() throws Exception { // 在每個測試方法執行 [之后] 都會被調用,多用于釋放資源
    System.out.println("Junit單元測試結束...");
  }
  public void testDivideByZero() {
    Throwable te = null;
    try {
      operation.divide(6, 0);
      Assert.fail("測試失敗"); //斷言失敗
    } catch (Exception e) {
      e.printStackTrace();
      te = e;
    }
    Assert.assertEquals(Exception.class, te.getClass());
    Assert.assertEquals("除數不能為 0 ", te.getMessage());
  }
}

4.2 JUnit 4.X

(1)使用 JUnit 4.X 版本進行單元測試時,不用測試類繼承TestCase父類;
(2)JUnit 4.X 版本,引用了注解的方式進行單元測試;
(3)JUnit 4.X 版本我們常用的注解包括:

@Before 注解:與JUnit 3.X 中的 setUp() 方法功能一樣,在每個測試方法之前執行,多用于初始化;
@After 注解:與 JUnit 3.X 中的 tearDown() 方法功能一樣,在每個測試方法之后執行,多用于釋放資源;
@Test(timeout = xxx) 注解:設置當前測試方法在一定時間內運行完,否則返回錯誤;
@Test(expected = Exception.class) 注解:設置被測試的方法是否有異常拋出。拋出異常類型為:Exception.class;

此外,我們可以通過閱讀上面的第二部分“2 注解”了解更多的注解。

/**
* 用 JUnit 4.X 進行測試
*/
import static org.junit.Assert.*;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
public class TestOperation {
  private Operation operation;
  @BeforeClass
  public static void globalInit() { // 在所有方法執行之前執行
    System.out.println("@BeforeClass標注的方法,在所有方法執行之前執行...");
  }
  @AfterClass
  public static void globalDestory() { // 在所有方法執行之后執行
    System.out.println("@AfterClass標注的方法,在所有方法執行之后執行...");
  }
  @Before
  public void setUp() { // 在每個測試方法之前執行
    System.out.println("@Before標注的方法,在每個測試方法之前執行...");
    operation = new Operation();
  }
  @After
  public void tearDown() { // 在每個測試方法之后執行
    System.out.println("@After標注的方法,在每個測試方法之后執行...");
  }
  @Test(timeout=600)
  public void testAdd() { // 設置限定測試方法的運行時間 如果超出則返回錯誤
    System.out.println("測試 add 方法...");
    int result = operation.add(2, 3);
    assertEquals(5, result);
  }
  @Test
  public void testSubtract() {
    System.out.println("測試 subtract 方法...");
    int result = operation.subtract(1, 2);
    assertEquals(-1, result);
  }
  @Test
  public void testMultiply() {
    System.out.println("測試 multiply 方法...");
    int result = operation.multiply(2, 3);
    assertEquals(6, result);
  }
  @Test
  public void testDivide() {
    System.out.println("測試 divide 方法...");
    int result = 0;
    try {
      result = operation.divide(6, 2);
    } catch (Exception e) {
      fail();
    }
    assertEquals(3, result);
  }
  @Test(expected = Exception.class)
  public void testDivideAgain() throws Exception {
    System.out.println("測試 divide 方法,除數為 0 的情況...");
    operation.divide(6, 0);
    fail("test Error");
  }
  public static void main(String[] args) {
  }
}

4.3 特別提醒

通過以上兩個例子,我們已經可以大致知道 JUnit 3.X 和 JUnit 4.X 兩個版本的區別啦!首先,如果我們使用 JUnit 3.X,那么在我們寫的測試類的時候,一定要繼承 TestCase 類,但是如果我們使用 JUnit 4.X,則不需繼承 TestCase 類,直接使用注解就可以啦!在 JUnit 3.X 中,還強制要求測試方法的命名為“ testXxxx ”這種格式;在 JUnit 4.X 中,則不要求測試方法的命名格式,但作者還是建議測試方法統一命名為“ testXxxx ”這種格式,簡潔明了。

此外,在上面的兩個示例中,我們只給出了測試類,但是在這之前,還應該有一個被測試類,也就是我們真正要實現功能的類。現在,作者將給出上面示例中被測試的類,即 Operation 類:

/**
* 定義了加減乘除的法則
*/
public class Operation {
  public static void main(String[] args) {
    System.out.println("a + b = " + add(1,2));
    System.out.println("a - b = " + subtract(1,2));
    System.out.println("a * b = " + multiply(1,2));
    System.out.println("a / b = " + divide(4,2));
    System.out.println("a / b = " + divide(1,0));
  }
  public static int add(int a, int b) {
    return a + b;
  }
  public static int subtract(int a, int b) {
    return a - b;
  }
  public static int multiply(int a, int b) {
    return a * b;
  }
  public static int divide(int a, int b) {
    return a / b;
  }
}

5 測試示例

5.1 示例一:簡單的 JUnit 3.X 測試

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import java.util.ArrayList;
import java.util.Collection;
/**
 * 1、創建一個測試類,繼承TestCase類
 */
public class SimpleTestDemo extends TestCase {
  public SimpleTestDemo(String name) {
    super(name);
  }
  /**
   * 2、寫一個測試方法,斷言期望的結果
   */
  public void testEmptyCollection(){
    Collection collection = new ArrayList();
    assertTrue(collection.isEmpty());
  }
  /**
   * 3、寫一個suite()方法,它會使用反射動態的創建一個包含所有的testXxxx方法的測試套件
   */
  public static Test suit(){
    return new TestSuite(SimpleTestDemo.class);
  }
  /**
   * 4、寫一個main()方法,以文本運行器的方式方便的運行測試
   */
  public static void main(String[] args) {
    junit.textui.TestRunner.run(suit());
  }
}

5.2 示例二:套件測試

首先,介紹一下套件測試,簡單來講,測試套件是指:一些測試不同類的用例,可以使用 @RunWith 和 @Suite 注解把所有的測試類套在一起,從而形成測試套件。如果有很多測試類,想讓它們都運行在同一時間,而不是單一地運行每個測試,套件測試是非常有用的。當一個類被注解為 @RunWith, JUnit 將調用其中的注解,以便運行測試類,而不使用內置的 JUnit 運行方法。

/**
* 待測試類
*/
import java.util.Arrays;
public class GotoWork {
  public String[] prepareSkills() {
    String[] skill = { "Java", "MySQL", "JSP" };
    System.out.println("My skills include : " + Arrays.toString(skill));
    return skill;
  }
  public String[] addSkills() {
    String[] skill = { "Java", "MySQL", "JSP", "JUnit" };
    System.out.println("Look, my skills include : " + Arrays.toString(skill));
    return skill;
  }
}
/**
* 測試類 1
*/
import org.junit.Test;
import static org.junit.Assert.*;
public class PrepareSkillsTest {
  GotoWork gotoWork = new GotoWork();
  String[] skill = { "Java", "MySQL", "JSP" };
  @Test
  public void testPrepareSkills() {
    System.out.println("Inside testPrepareSkills()");
    assertArrayEquals(skill, gotoWork.prepareSkills());
  }
}
/**
* 測試類 2
*/
import org.junit.Test;
import static org.junit.Assert.*;
public class AddSkillsTest {
  GotoWork gotoWork = new GotoWork();
  String[] skill = { "Java", "MySQL", "JSP", "JUnit" };
  @Test
  public void testAddSkills() {
    System.out.println("Inside testAddPencils()");
    assertArrayEquals(skill, gotoWork.addSkills());
  }
}
/**
* 套件測試
*/
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
@RunWith(Suite.class)
@Suite.SuiteClasses({ PrepareSkillsTest.class, AddSkillsTest.class })
public class SuitTest {
}

使用 @Suite.SuiteClasses 注解,可以定義測試類,將被列入執行,并且執行的順序就是在 @Suite.SuiteClasses 注解中定義的順序。

5.3 示例三:參數化測試

首先介紹一下參數化測試,一個測試類可以被看作是一個參數化測試類,當其滿足下列所有要求:

① 該類被注解為 @RunWith(Parameterized.class);
② 該類有一個構造函數,存儲測試數據;
③ 該類有一個靜態方法生成并返回測試數據,并標注 @Parameters 注解;
④ 該類有一個測試方法,即用注解 @Test 標注的方法。

/**
* 待測試類
*/
public class Calculate {
  public int sum(int var1, int var2) {
    System.out.println("此方法的參數值分別為 : " + var1 + " + " + var2);
    return var1 + var2;
  }
}
/**
* 參數化測試類
*/
import static org.junit.Assert.assertEquals;
import java.util.Arrays;
import java.util.Collection;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
@RunWith(Parameterized.class)
public class CalculateTest {
  private int expected;
  private int first;
  private int second;
  public CalculateTest(int expectedResult, int firstNumber, int secondNumber) {
    this.expected = expectedResult;
    this.first = firstNumber;
    this.second = secondNumber;
  }
  @Parameters
  public static Collection addedNumbers() {
    return Arrays.asList(new Integer[][] { { 3, 1, 2 }, { 5, 2, 3 }, { 7, 3, 4 }, { 9, 4, 5 }, });
  }
  @Test
  public void testSum() {
    Calculate add = new Calculate();
    System.out.println("Addition with parameters : " + first + " and " + second);
    assertEquals(expected, add.sum(first, second));
  }
}

觀察 CalculateTest 類,它滿足上述所有的要求,因此它就可以稱為一個參數化測試類。addedNumbers 方法使用注釋 @Parameters 返回數組的集合,每個數組包括每個測試執行輸入和輸出數字,每個數組中的元素數必須相同好與構造參數的個數相匹配。所以,在這種特定的情況下,每個數組包括三個元素,即表示要加入的兩個元素和一個結果元素。

6 個人建議

有些童鞋可能會有一些誤解,認為寫測試代碼沒有用,而且還會增大自己的壓力,浪費時間。但事實上,寫測試代碼與否,還是有很大區別的,如果是在小的項目中,或許這種區別還不太明顯,但如果在大型項目中,一旦出現錯誤或異常,用人力去排查的話,那將會浪費很多時間,而且還不一定排查的出來,但是如果用測試代碼的話,JUnit 就是自動幫我們判斷一些代碼的結果正確與否,從而節省的時間將會遠遠超過你寫測試代碼的時間。

因此,個人建議:要養成編寫測試代碼的習慣,碼一點、測一點;再碼一點,再測一點,如此循環。在我們不斷編寫與測試代碼的過程中,我們將會對類的行為有一個更為深入的了解,從而可以有效的提高我們的工作效率。下面,作者就給出一些具體的編寫測試代碼的技巧和較好的實踐方法:

1. 不要用 TestCase 的構造函數初始化 Fixture,而要用 setUp() 和 tearDown() 方法;
2. 不要依賴或假定測試運行的順序,因為 JUnit 會利用 Vector 保存測試方法,所以不同的平臺會按不同的順序從 Vector 中取出測試方法;
3. 避免編寫有副作用的 TestCase,例如:如果隨后的測試依賴于某些特定的交易數據,就不要提交交易數據,只需要簡單的回滾就可以了;
4. 當繼承一個測試類時,記得調用父類的 setUp() 和 tearDown() 方法;
5. 將測試代碼和工作代碼放在一起,同步編譯和更新;
6. 測試類和測試方法應該有一致的命名方案,如在工作類名前加上 test 從而形成測試類名;
7. 確保測試與時間無關,不要使用過期的數據進行測試,以至于導致在隨后的維護過程中很難重現測試;
8. 如果編寫的軟件面向國際市場,那么編寫測試時一定要考慮國際化的因素;
9. 盡可能地利用 JUnit 提供地 assert 和 fail 方法以及異常處理的方法,其可以使代碼更為簡潔;
10. 測試要盡可能地小,執行速度快;
11. 不要硬性規定數據文件的路徑;
12. 使用文檔生成器做測試文檔。

看完了這篇文章,相信你對“java單元測試JUnit框架原理的示例分析”有了一定的了解,如果想了解更多相關知識,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

得荣县| 樟树市| 财经| 郁南县| 万年县| 汽车| 伊通| 西宁市| 南充市| 罗江县| 长沙县| 肃宁县| 峨眉山市| 新化县| 博兴县| 集贤县| 杭锦旗| 商城县| 西乡县| 锡林郭勒盟| 天镇县| 从化市| 承德县| 仙游县| 涪陵区| 桂阳县| 华容县| 蓬安县| 宁明县| 宿州市| 二手房| 房产| 吉隆县| 邵武市| 卫辉市| 塔城市| 张家川| 尖扎县| 延津县| 天台县| 轮台县|