JUnit學習筆記(一):基本用法
阿新 • • 發佈:2019-01-03
JUnit學習筆記(一):基本用法
JUnit是Java的單元測試框架。JUnit提倡“先測試後編碼”的理念,強調建立測試資料的程式碼,可以先測試,再應用。
框架的特點:
JUnit是開放的資源框架,用於編寫和執行測試; 提供註釋來識別測試的方法;
提供斷言來測試預期結果;
提供測試執行來執行測試;
單元測試用例的特點: 預期輸入和預期輸出。預期輸入需要有測試的前置條件,預期輸出需要有測試的後置條件;
每一項需求至少需要兩個單元測試用例:一個正向驗證(是否做了該做的事),一個負向驗證(是否做了不該做的事)。 若一個需求有子需求,每一個子需求必須至少有 正向驗證和負向驗證兩個測試用例。負向用例可以有多個;
API:
官網API地址:http://junit.org/junit4/javadoc/latest/index.html
核心包junit.framework和junit.runner。Framework包-->整個測試物件的構架,Runner-->測試驅動;
JUnit的四個核心類:TestCase、TestSuite、TestRunner、TestResult; TestResult: 測試結果。收集TestCase所執行的結果,將結果分為兩類,可預測的Failure和沒有預測的Error。同時將測試結果
轉發到TestListener(該介面由TestRunner繼承)處理;
TestRunner: 測試執行器。物件呼叫的起始點,對整個測試流程的跟蹤。能顯示返回的測試結果,並且報告測試的進度;
TestSuite: 測試集合。包裝和執行所有的TestCase;
TestCase: 測試用例。測試類所要繼承的類,測試時對被測試類進行初始化,及測試方法呼叫;
重要的介面:Test和TestListener Test的主要方法:run()和countTestCases();
TestListener的主要方法:addError()、addFailure()、startTest()和endTest();
基本的測試過程:
TestClass.class(被測試類)-->TestCase(測試用例)-->TestSuite(測試用例集合)-->TestRunner(測試執行器)-->TestResult(測試結果)
例子:
Ignoring Tests 含有@Ignore註釋的測試方法將不會被執行;
用@Ignore註釋的測試類,它的測試方法將不會執行;
例子:
Timeout for Tests
設定超時時間,對用例執行時間進行控制。 第一種用法:
Exception Testing
測試程式碼是否丟擲預想的異常。 例子:
Parameterized Tests
引數化測試允許使用不同的值反覆運行同一個測試。可以按照以下步驟來建立引數化測試:
用 @RunWith(Parameterized.class) 來註釋 test 類; 建立一個由 @Parameters 註釋的公共的靜態方法,它返回一個物件的集合(陣列)來作為測試資料集合; 建立一個公共的建構函式,它接受和一行測試資料相等同的東西; 為每一列測試資料建立一個例項變數;
用例項變數作為測試資料的來源來建立你的測試用例;
例子:
Rules
@ClassRule:set up the external resource in your example. @Rule:resetting the resource in that example. 參考: http://wiki.jikexueyuan.com/project/junit/ http://junit.org/junit4/ http://stackoverflow.com/questions/20767486/combining-classrule-and-rule-in-junit-4-11
注:
框架的特點:
JUnit是開放的資源框架,用於編寫和執行測試; 提供註釋來識別測試的方法;
提供斷言來測試預期結果;
提供測試執行來執行測試;
單元測試用例的特點: 預期輸入和預期輸出。預期輸入需要有測試的前置條件,預期輸出需要有測試的後置條件;
每一項需求至少需要兩個單元測試用例:一個正向驗證(是否做了該做的事),一個負向驗證(是否做了不該做的事)。 若一個需求有子需求,每一個子需求必須至少有
JUnit的四個核心類:TestCase、TestSuite、TestRunner、TestResult; TestResult: 測試結果。收集TestCase所執行的結果,將結果分為兩類,可預測的Failure和沒有預測的Error。同時將測試結果
TestRunner: 測試執行器。物件呼叫的起始點,對整個測試流程的跟蹤。能顯示返回的測試結果,並且報告測試的進度;
TestSuite: 測試集合。包裝和執行所有的TestCase;
TestCase: 測試用例。測試類所要繼承的類,測試時對被測試類進行初始化,及測試方法呼叫;
重要的介面:Test和TestListener Test的主要方法:run()和countTestCases();
TestListener的主要方法:addError()、addFailure()、startTest()和endTest();
public class Message { //被測試類
private String message = null;
public boolean isPrint = false;
public Message(String message) {
this.message = message;
}
public String printMessage() { // method1-->case1
System.out.println(message);
this.isPrint = true;
System.out.println(this.isPrint + "...");
return this.message;
}
public String changeMessage(String str) { // method2-->case2
this.message += str;
return this.message;
}
public String handleMessage(String str){ // method3-->case3
int a = str.length();
if(a>=5){
this.message = str.substring(0, 5);
}
return this.message;
}
}
public class MessageTestCase1 { //測試用例1
String info = "new String";
Message m = new Message(info);
@Test
public void test1() {
m.printMessage();
assertEquals(true, m.isPrint);
}
@Test
public void test2() {
m.printMessage();
assertEquals(false, m.isPrint);
}
}
public class MessageTestCase2 { //測試用例2
String s = "aa";
Message m = new Message(s);
@Test
public void test1(){
String str = "aazz";
assertEquals(str,m.changeMessage("zz"));
}
@Test
public void test2(){
String str = "asdf";
assertEquals(str,m.changeMessage(str));
}
}
public class MessageTestCase3 { //測試用例3
String str = "abcdefgh";
Message m = new Message("a");
@Test
public void test1(){
assertEquals(5,m.handleMessage(str).length());
}
@Test
public void test2(){
assertEquals(4,m.handleMessage(str).length());
}
@Test
public void test3(){
assertEquals(6,m.handleMessage(str).length());
}
}
@RunWith(Suite.class)
@Suite.SuiteClasses({ MessageTestCase1.class, MessageTestCase2.class,
MessageTestCase3.class })
public class MessageTestSuite { //測試用例集
// public static void main(String[] args) {
//
// TestSuite suite = new TestSuite(MessageTestCase1.class,
// MessageTestCase2.class,MessageTestCase3.class);
//
// TestResult result = new TestResult();
// suite.run(result);
//
// }
}
public class MessageTestRunner { //測試執行器
public static void main(String[] args) {
Result result = JUnitCore.runClasses(MessageTestSuite.class);
for (Failure failure : result.getFailures()) {
System.out.println(failure.toString());
}
System.out.println("TestResult:" + result.wasSuccessful());
}
}
Ignoring Tests 含有@Ignore註釋的測試方法將不會被執行;
用@Ignore註釋的測試類,它的測試方法將不會執行;
例子:
@Ignore("冗餘測試用例")
@Test
public void test3(){
assertEquals(6,m.handleMessage(str).length());
}
Timeout for Tests
設定超時時間,對用例執行時間進行控制。 第一種用法:
@Test(timeout=10000)
public void test2(){
assertEquals(4,m.handleMessage(str).length());
}
第二種用法(設定超時規則。寫在測試類中,測試類中的所有測試方法均遵守此規則):@Rule
public Timeout globalTimeout = Timeout.seconds(10);
Exception Testing
測試程式碼是否丟擲預想的異常。 例子:
Class.forName("jdbc.mysql.Driver");
@Test(expected = ClassNotFoundException.class)
public void test1() {
Class.forName("jdbc.mysql.Driver");
}
Parameterized Tests
引數化測試允許使用不同的值反覆運行同一個測試。可以按照以下步驟來建立引數化測試:
用 @RunWith(Parameterized.class) 來註釋 test 類; 建立一個由 @Parameters 註釋的公共的靜態方法,它返回一個物件的集合(陣列)來作為測試資料集合; 建立一個公共的建構函式,它接受和一行測試資料相等同的東西; 為每一列測試資料建立一個例項變數;
用例項變數作為測試資料的來源來建立你的測試用例;
例子:
public class Test123 { //被測試類
private Integer a;
private Integer b;
public int add(int a, int b) { //
return a + b;
}
}
@RunWith(Parameterized.class)
public class TestCase { //使用引數化的 測試用例
private Integer input1;
private Integer input2;
private Integer result;
public TestCase(Integer a, Integer b, Integer c) {
this.input1 = a;
this.input2 = b;
this.result = c;
}
@Parameters
public static Collection addNumbers() {
return Arrays.asList(new Object[][] { { 1, 2, 3 }, { -6, -3, -9 },
{ 1, -6, -5 }, { 2, 0, 6 }, { 99, 9, 108 } });
}
@Test
public void test1() {
Test123 t =new Test123();
assertEquals(result.intValue(), t.add(input1, input2));
}
}
Rules
@ClassRule
public static Service service = Service.getInstance(); //必須是靜態的
@Rule
public Service tmp = service;
@ClassRule:set up the external resource in your example. @Rule:resetting the resource in that example. 參考: http://wiki.jikexueyuan.com/project/junit/ http://junit.org/junit4/ http://stackoverflow.com/questions/20767486/combining-classrule-and-rule-in-junit-4-11
注: