單元測試是編寫測試代碼,應該準確、快速地保證程序基本模塊的正確性。
好的單元測試的標準
JUnit是Java單元測試框架,已經在Eclipse中默認安裝。html
JUnit4經過註解的方式來識別測試方法。目前支持的主要註解有:框架
基本測試eclipse
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; } }
public class CalculatorTest { private static Calculator calculator = new Calculator(); @Before public void setUp() throws Exception { calculator.clear(); } @Test public void testAdd() { calculator.add(3); calculator.add(4); assertEquals(7, calculator.getResult()); } @Test public void testSubstract() { calculator.add(8); calculator.substract(3); assertEquals(5, calculator.getResult()); } @Ignore("Multiply() Not yet implemented") @Test public void testMultiply() { fail("Not yet implemented"); } @Test public void testDivide() { calculator.add(8); calculator.divide(2); assertEquals(4, calculator.getResult()); } }
@Test(timeout = 1000) public void squareRoot() { calculator.squareRoot(4); assertEquals(2, calculator.getResult()); }
Timeout參數代表了你要設定的時間,單位爲毫秒,所以1000就表明1秒。ide
JAVA中的異常處理也是一個重點,所以你常常會編寫一些須要拋出異常的函數。那麼,若是你以爲一個函數應該拋出異常,可是它沒拋出,這算不算Bug呢?這固然是Bug,並JUnit也考慮到了這一點,來幫助咱們找到這種Bug。例如,咱們寫的計算器類有除法功能,若是除數是一個0,那麼必然要拋出「除0異常」。所以,咱們頗有必要對這些進行測試。代碼以下:函數
@Test(expected = ArithmeticException.class) public void divideByZero(){ calculator.divide(0); }
如上述代碼所示,咱們須要使用@Test標註的expected屬性,將咱們要檢驗的異常傳遞給他,這樣JUnit框架就能自動幫咱們檢測是否拋出了咱們指定的異常。
參數化測試
咱們可能遇到過這樣的函數,它的參數有許多特殊值,或者說他的參數分爲不少個區域。
例如,測試一下「計算一個數的平方」這個函數,暫且分三類:正數、0、負數。在編寫測試的時候,至少要寫3個測試,把這3種狀況都包含了,這確實是一件很麻煩的事情。測試代碼以下:單元測試
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提出了「參數化測試」的概念,只寫一個測試函數,把這若干種狀況做爲參數傳遞進去,一次性的完成測試。代碼以下:測試
@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}, }); } //構造函數,對變量進行初始化 public SquareTest(int param, int result){ this.param = param; this.result = result; } @Test public void square(){ calculator.square(param); assertEquals(result, calculator.getResult()); } }
執行了3次該測試類,依次採用了數據集合中的數據{處理值,預期處理結果},結果以下:
代碼分析以下:ui