以下是我在看完浪曦網的風中葉老師的jUnit3.8教學後整理的學習筆記:
1. 建立一個工程,取名隨意。
2. 建立包(com.test.junit3),並建立一個計算類(Calculator),添加其相應的方法。完成後代碼如下:
public class Calculator {
public int add(int a, int b) {
return a + b;
}
public int minus(int a, int b) {
return a - b;
}
public int multiply(int a, int b) {
return a * b;
}
public int divide(int a, int b) throws Exception {
if (0 == b) {
throw new Exception("除數不能爲0!");
}
return a / b;
}
}
這裏面的方法比較簡單,不在解釋。
3. 建立測試類。
a. 建立測試類的時候(我指的是使用Eclipse或者MyEclipse進行開發的時候),一般將測試類放到另外一個源文件夾中。在項目上點右鍵,選擇new-->Source Folder。名字隨意,一般取名字test。
b. 建立測試包。包名一般與需要被測試的類的包名相同,在這裏,包名與Calculator類的包名相同(com.test.junit3)。
c. 建立測試類。測試類命名一般是需要被測試的類名加上後綴“Test”,這裏爲CalculatorTest。
4. 測試類需要注意的方面。在這裏,也就是CalculatorTest需要遵守的規則。
a. 測試類必須繼承TestCase類。
b. 測試方法必須爲public型的,void的,沒有方法參數,且方法名必須以“test”爲前綴,即以test開頭(如果不以test開頭,那該方法需要手動啓動測試。運行測試類的時候,該方法是無法被自動進行測試的)。
5. 實際的測試類。
package com.test.junit3;
import junit.framework.Assert;
import junit.framework.TestCase;
public class CalculatorTest extends TestCase{
private Calculator cal;
/**
* 執行每一個測試方法的時候,先執行setUp();
*/
protected void setUp() throws Exception {
cal=new Calculator();
}
/**
* 執行每一個測試方法之後,執行tearDown();
*/
protected void tearDown() throws Exception {
super.tearDown();
}
public void testAdd(){
int result=cal.add(1, 2);
//斷言:assert
Assert.assertEquals(3, result);
}
public void testMinus(){
int result =cal.minus(1, 2);
Assert.assertEquals(-1, result);
}
public void testMultiply(){
int result =cal.multiply(2, 3);
Assert.assertEquals(6, result);
}
public void testDivied(){
int result=0;
try {
result = cal.divide(6, 4);
} catch (Exception e) {
e.printStackTrace();
Assert.fail();
}
Assert.assertEquals(1, result);
}
public void testDivied2(){
Throwable tx=null;
try {
cal.divide(4, 0);
Assert.fail();
} catch (Exception e) {
tx=e;
}
//斷言tx是否爲空
Assert.assertNotNull(tx);
//斷言兩個對象是否相同
Assert.assertEquals(Exception.class,tx.getClass());
//斷言String是否相同
Assert.assertEquals("除數不能爲0!", tx.getMessage());
}
}
a. 如果被測試的方法絕對不會有異常拋出(如:Calculator中的add(int a,int b)),那麼在測試類(CalculatorTest)中可以像下面的代碼一樣,直接使用斷言Assert類中的assertEquals(int expected, int actual)方法直接斷言。該方法傳入兩個int參數,一個表示期望值,即按照設計應該得到的結果expected,一個表示實際值,即程序實際得到的結果actual。如果這兩個結果相同,則表示被測試的類即(Calculator)中的該方法沒有錯誤。
public void testAdd(){
int result=cal.add(1, 2);
//斷言:assert
Assert.assertEquals(3, result);
}
補充:Assert中的assertEquals()方法傳入的參數基本可以是所有的類型,包括String、int、char等等,具體的自己看。注意:預期值和實際值的類型必須一致。
b. 如果被測試的方法有異常拋出(如:Calculator中的divied(int a,int b)),那麼在測試類中如果直接使用斷言Assert中的assertEquals(int expected, int actual)方法時,傳入參數b爲0的時候,如下:
public void testDivied(){
int result=0;
try {
result = cal.divide(6, 0);
} catch (Exception e) {
e.printStackTrace();
Assert.fail();
}
Assert.assertEquals(1, result);
}
無論你的代碼是否完善,是否已經正確無誤了,TestBar顯示仍爲紅條,表示該方法無法通過測試。正確的寫法應該如下:
public void testDivied2(){
//Throwable爲Exception和Error的父類.
Throwable tx=null;
try {
cal.divide(4, 0);
Assert.fail();
} catch (Exception e) {
tx=e;
}
//斷言tx是否爲空
Assert.assertNotNull(tx);
//斷言兩個對象是否相同
Assert.assertEquals(Exception.class,tx.getClass());
//斷言異常信息是否爲指定異常信息。tx.getMessage()獲取異常拋出的信息
Assert.assertEquals("除數不能爲0!", tx.getMessage());
}
“Assert.fail;”表示該方法測試失敗,它的目的是:假如它被執行到了,那麼表示divide(int a,int b)方法沒有拋出異常,也就是方法中有bug。
“tx=e;”將異常e賦給tx,將局部變量賦給全局變量,以便進行下面操作。
“Assert.assertNotNull(tx);”斷言tx是否爲空,如果tx爲空,則說明divide(int a,int b)方法沒有將異常拋出,方法中存在bug。
“Assert.assertEquals(Exception.class,tx.getClass());”。tx.getClass()可以得到tx,也就是這個異常是哪個類,然後斷言是否與你期望的異常類相同。如果不同,測試失敗,方法拋出異常錯誤,方法中存在bug。其實到這裏可以結束了,而“Assert.assertEquals("除數不能爲0!",tx.getMessage());”是爲了通過斷言異常信息,更進一步判斷該異常是否是你在方法中指定的異常。
這樣,通過這些斷言,可以保證你的方法目前沒有發現bug存在,測試的時候,該方法會通過,表現方式爲TestBar爲綠色通過。
6. 在測試的時候,再TestCase中有兩個方法,一個爲setUp(),表示初始化。該方法在每個測試方法執行之前將被首先執行。比如如果要執行testAdd()方法的時候,先要執行一遍setUp()方法。因此該方法一般進行一些初始化操作,比如對被測試類的實例化,如:
protected void setUp() throws Exception {
cal=new Calculator();
}
另一個方法爲tearDown(),該方法在每個測試方法執行之後執行,因此該方法一般處理每個測試方法結束後的資源釋放操作。
總的來說:如果測試類中有3個測試方法test1(),test2(),test3(),那麼方法的執行順序爲
setUp()->test1()->tearDown()->setUp()->test2()->tearDown()->setUp()->test3()->tearDown()
7. 測試的時候,一般要注意臨界值的測試。如除數不能爲0,索引越界等問題。
8. 如果在沒有IDE的情況下,可以通過使用TestRunner類進行測試,如以下代碼所示
public static void main(String[] args) {
junit.awtui.TestRunner.run(CalculatorTest.class);
}
需要注意的是:在junit.awtui、junit.swingui和junit.textui三個包下均有TestRunner類,任何一個類都可以執行測試任務。只是表現的方式不同,看你喜歡用哪個了!
9. 在執行多個測試類的時候,一個一個點運行,進行測試顯然是非常費時的事情。junit提供了一個類TestSuite可以將多個測試類一起運行,進行測試。示例代碼如下:
package com.test.junit3;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
public class TestAll extends TestCase {
/**
* 該方法名稱必須爲suite(),不能更改
* 該方法中
* TestSuite對象不僅可以添加測試類,還可以包裝suite對象
* @return
*/
public static Test suite(){
TestSuite suite=new TestSuite();
suite.addTestSuite(LargestTest.class);
suite.addTestSuite(CalculatorTest.class);
return suite;
}
}
如註釋所示,該靜態方法名稱必須爲suite(),原因可以參看junit源代碼。另外該方法返回Test對象。TestSuite中有兩個方法很重要,一個是addTestSuite(),可以直接添加測試類。另一個方法爲addTest(),可以添加TestSuite對象,所以,上面也可以通過下面的代碼實現:
package com.test.junit3;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
public class TestAll extends TestCase {
public static Test suite(){
TestSuite suite=new TestSuite();
TestSuite suite1=new TestSuite();
suite1.addTestSuite(LargestTest.class);
TestSuite suite2=new TestSuite();
suite2.addTestSuite(CalculatorTest.class);
suite.addTest(suite1);
suite.addTest(suite2);
return suite;
}
}
這樣我們可以方便的對多個測試類進行測試了。
最後,感謝風老師的視頻!