測試程式碼地址:https://github.com/zllwxq130/test/blob/master/junittest.java
1.編寫目標類原始碼
package com.mengdd.junit;
public class Calculator
{
public int add(int a, int b)
{
return a + b;
}
public int subtract(int a, int b)
{
return a - b;
}
public int multiply(int a, int b)
{
return a * b;
}
public int divide(int a, int b)
{
return a / b;
}
}
- 新增JUnit庫
然後為了使用JUnit,需要加入庫:
右鍵選擇專案Properties->左側Java Build Path->標籤Libraries->Add Library...
彈出的對話方塊中選JUnit,然後Next,再選擇JUnit 3或者JUnit 4.
本文示例選擇JUnit 3。
- 建立測試類
這裡需要注意以下幾點:
1.使用JUnit的最佳實踐:原始碼和測試程式碼需要分開。
所以可以新建一個名叫test的source folder,用於存放測試類原始碼。這樣在釋出程式的時候測試類的程式就可以丟掉了。
但是這兩個資料夾中的類編譯出的class檔案都會在同一個bin資料夾中。
2.測試類和目標原始碼的類應該位於同一個包下面,即它們的包名應該一樣。 這樣測試類中就不必匯入原始碼所在的包,因為它們位於同一個包下面。
3.測試類的命名規則:
在要測試的類名之前或之後加上Test。
此步驟完成後專案目錄如下:
- 測試類程式碼編寫
測試類必須繼承於TestCase類。
TestCase文件說明:
public abstract class TestCase
extends Assert
implements Test
A test case defines the fixture to run multiple tests. To define a test case
1) implement a subclass of TestCase
2) define instance variables that store the state of the fixture
3) initialize the fixture state by overriding setup
4) clean-up after a test by overriding tearDown.
Each test runs in its own fixture so there can be no side effects among test runs.
對於測試類中方法的要求:
在JUnit 3.8中,測試方法需要滿足如下原則:
1.public的。
2.void的。
3.無方法引數。
4.方法名稱必須以test開頭。 (它通過反射找出所有方法,然後找出以test開頭的方法)。
Test Case之間一定要保持完全的獨立性,不允許出現任何的依賴關係。
刪除一些方法後不會對其他的方法產生任何的影響。
我們不能依賴於測試方法的執行順序。
綜上,編寫程式碼如下:
package com.mengdd.junit;
import junit.framework.Assert;
import junit.framework.TestCase;
public class CalculatorTest extends TestCase
{
public void testAdd()
{
Calculator calculator = new Calculator();
int result = calculator.add(1, 2);
// 判斷方法的返回結果
Assert.assertEquals(3, result);// 第一個引數是期望值,第二個引數是要驗證的值
}
public void testSubtract()
{
Calculator calculator = new Calculator();
int result = calculator.subtract(1, 2);
// 判斷方法的返回結果
Assert.assertEquals(-1, result);// 第一個引數是期望值,第二個引數是要驗證的值
}
public void testMultiply()
{
Calculator calculator = new Calculator();
int result = calculator.multiply(2, 3);
// 判斷方法的返回結果
Assert.assertEquals(6, result);// 第一個引數是期望值,第二個引數是要驗證的值
}
public void testDivide()
{
Calculator calculator = new Calculator();
int result = calculator.divide(12, 3);
// 判斷方法的返回結果
Assert.assertEquals(4, result);// 第一個引數是期望值,第二個引數是要驗證的值
}
}
執行一下:右鍵選擇該類,Run As->JUnit Test
JUnit的口號:Keep the bar green to keep the code clean.
- 程式碼重構:setUp()方法的使用
有一個原則:DRY(Don’t Repeat Yourself)
所以對程式碼進行重構,將重複的生成物件的部分放在setUp()方法中。
(重寫的時候將protected變為public,繼承的時候擴大訪問範圍是沒有問題的。) 先進行一個方法的測試測試:
在CalculatorTest類中加入程式碼如下:
@Override
public void setUp() throws Exception
{
System.out.println("set up");
}
@Override
public void tearDown() throws Exception
{
System.out.println("tear down");
}
再次執行後發現Console中輸出如下:
說明這兩個方法執行了多次。
在每個測試用例之前執行setUp(),每個測試用例執行之後,tearDown()會執行。
即對於每個測試用例,執行順序為:
1.setUp()
2.testXXX()
3.tearDown()
重構:使用成員變數生成物件(為了能在每個方法中都用到),將生成物件的語句放在setUp()中,注意這裡為每一個測試用例都會生成新的物件。
重構後程式碼如下:
package com.mengdd.junit;
import junit.framework.Assert;
import junit.framework.TestCase;
public class CalculatorTest extends TestCase
{
private Calculator calculator = null;
@Override
public void setUp() throws Exception
{
System.out.println("set up");
// 生成成員變數的例項
calculator = new Calculator();
System.out.println(calculator);
}
@Override
public void tearDown() throws Exception
{
System.out.println("tear down");
}
public void testAdd()
{
int result = calculator.add(1, 2);
// 判斷方法的返回結果
Assert.assertEquals(3, result);// 第一個引數是期望值,第二個引數是要驗證的值
}
public void testSubtract()
{
int result = calculator.subtract(1, 2);
// 判斷方法的返回結果
Assert.assertEquals(-1, result);// 第一個引數是期望值,第二個引數是要驗證的值
}
public void testMultiply()
{
int result = calculator.multiply(2, 3);
// 判斷方法的返回結果
Assert.assertEquals(6, result);// 第一個引數是期望值,第二個引數是要驗證的值
}
public void testDivide()
{
int result = calculator.divide(12, 3);
// 判斷方法的返回結果
Assert.assertEquals(4, result);// 第一個引數是期望值,第二個引數是要驗證的值
}
}
執行後控制檯輸出:
說明每一個測試的方法前後都會有setUp()和tearDown()方法的呼叫,所以每次生成的都是一個新的物件,各個方法之間沒有干擾。