Java 單元測試:
單元測試是開發者編寫的一小段代碼,用於檢測被測代碼的一個很小的、很明確的功能是否正確。
單元測試的方法:
人工靜態分析:人工閱讀檢測代碼
自動靜態分析:使用代碼複查工具檢查
自動動態測試:用工具自動生成測試用例並執行被測程序
人工動態測試:人工設定程序的輸入和預期輸出,執行程序。
Junit 單元測試:
它是人工動態測試
支持語言C++、Java,支持的IDE: Eclipse
功能:用單獨的classloader來運行每個單元測試
標準的資源初始化和回收方式(setUp、tearDown)
Eclipse 使用Junit測試的方法
1、導入 Junit Jar包,可以在Java Build Path 中添加,最好直接使用Eclipse 自帶的JUnit套件
2、爲單元測試代碼創建單獨的目錄,單元測試代碼和被測試代碼建議使用一樣的包層結構。比如src\com\lls\Person.java 和 testSrc\com\lls\PersonTest.java
3、創建單元測試類,可以直接通過Eclipse的Junit Test Case 功能進行添加,這樣就只需修改Source folder即可
下面內容爲Junit 4.0之後內容
4、Junix 包所定義的註解及其意義
方法註解
@Before - 它所修飾的方法在每個測試方法執行之前都要執行一次。 之前沒有註解的版本叫做setUp方法
@After - 它所修飾的方法在每個測試方法執行之後都要執行一次。 tearDown方法
@Test - 測試用的方法,他可以添加參數來對特定的情況進行驗證
比如@Test(expected=*.class) 表示的是異常的類型,如果沒有產生異常則失敗
@Test(timeout = xxx) 表示的是測試的最大時間,超時則認爲失敗
@ignore - 它所修飾的測試方法會被忽略
其中@Before 和@After 被稱爲Fixture,也就是每個測試之前都必須要執行的內容
5、測試方法使用要求
@Test
public void xxx(無參)
6、使用Eclipse的 Run as Juit來執行測試用例
如果與測試結果不符,則結果爲 失敗 failure
如果測試時,直接產生異常,則結果爲error
7、測試套件
也就是一次執行多個測試用例
方法:創建一個空類作爲測試套件的入口。使用註解RunWith和SuiteClasses修飾這個空類。
將org.junit.runners.Suite 作爲參數傳入註解RunWith,表示使用套件運行器執行。
將測試類組成數組作爲註解SuiteClasses的參數
比如:
@RunWith(Suite.class)
@Suite.SuiteClasses({xx1.class, xx2.class})
public class RunAllUtilTestsSuite {
}
原理及框架說明
8、Runner 運行器
在運行測試代碼的時候是通過Runner來運行(也就是Runner的子類),比如,默認的JUnit4Cla***unner(不過這個已經廢棄了,看來有了新的)
它可以用@RunWith 註解來說明,需要注意的是它修飾的是類
裏面包含兩個特殊的測試,參數化測試、套件打包測試
參數化測試:
@RunWith(Parameterized.class)
首先應該爲這種測試專門生成一個新的類,因爲他要用一個新的運行器。然後指定運行器爲Parameterized。
然後在測試類中定義兩個變量,一個用於存放參數,另一個存放期待的結果。接下來定義測試數據的集合,用@Parameters標註進行修飾。
構造函數中對變量進行初始化,順序需要與集合中的順序一致,比如{參數,預期結果}。
打包測試:
通常在一個項目中,我們需要寫很多個測試類,打包測試就是一次執行多個或所有的測試類.
@RunWith(Suite.class) // 指定運行器
@Suite.SuiteClass({..,..,..}) // 指定需要同時測試的類
待測試的類: package com.test; public class Calculator { private static int result;// 靜態變量,用於存儲運行結果 public void add(int n) { result = result + n; } public void substract(int n) { result = result - 1; // Bug: 正確的應該是 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 : 死循環 } public void clear() { // 將結果清零 result = 0; } public int getResult(){ return result; } } // ------------- 基本測試 package com.test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; import org.junit.After; 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(); } @After public void tearDown() throws Exception { } @Test public void testAdd() { calculator.add(2); calculator.add(3); assertEquals(5, calculator.getResult()); } @Test public void testSubstract() { calculator.add(2); calculator.add(3); assertEquals(5, calculator.getResult()); } @Ignore("not implemented yet") @Test public void testMultiply() { fail("Not yet implemented"); } @Test public void testDivide() { calculator.add(8); calculator.divide(2); assertEquals(4, calculator.getResult()); } @Test(expected = Exception.class) public void DivideByZero(){ calculator.divide(0); } } // ----------------- 多個參數測試 package com.test; import static org.junit.Assert.*; import java.util.Arrays; import java.util.Collection; import org.junit.After; import org.junit.Before; 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 SquareTest { Calculator calculator; private int param; private int result; public SquareTest(int param,int result) { this.param = param; this.result = result; } @Before public void setUp() throws Exception { calculator = new Calculator(); } @After public void tearDown() throws Exception { } @Parameters public static Collection data(){ return Arrays.asList( new Object[][]{{2,4},{0,0},{-2,4}}); } @Test public void testSquare() { calculator.square(param); assertEquals(calculator.getResult(),result ); } } // --------------- 打包測試 @RunWith(Suite.class) @Suite.SuiteClasses({CalculatorTest.class, SquareTest.class }) public class AllCalculator { }