前沿:
Android SDK 測試類是基于Junit3來進行擴充的,是以我們有必要了解Junit3,本文将詳細介紹Junit3的相關知識。
1.什麼是 JUnit
2.JUnit 的運作模式
1.定義測試代碼:這也就是 JUnit 中所謂的 TestCase,根據源代碼的測試需要定義每個TestCase,并将 TestCase 添加到相應的 TestSuite 友善管理。
2.管理測試用例:修改了哪些代碼,這些代碼的修改會對哪些部分有影響,通過 JUnit 将這次的修改做個完整測試。這也就 JUnit 中所謂的 TestSuite。
3.定義測試環境:在 TestCase 測試前會先調“環境”(如:參數化測試環境,套件測試環境)配置,在測試中使用,當然也可以在測試用例中直接定義測試環境。
4.檢測測試結果:對于每種正常、異常情況下的測試,運作結果是什麼、結果是否是我們預期的等都需要有個明确的定義,JUnit 在這方面提供了強大的功能。
簡單來說就是: TestCase -> TestSuite -> TestRunner ==> TestResult
3.如何在AndroidStudio上搭建Junit測試環境
版本:Window 7旗艦版
IDE:Android studio 2.2.3
gradleVersion :gradle 2.2.3
3.1 我們需要先搭建一個Junit的運作環境,由于我們是基于Android的單元測試系列,是以我們将介紹如何在Android Studio中搭建Junit運作環境:
在Adroid 視圖模式下,可以看到一個test 和 androidTest兩個檔案夾。Test檔案夾是進行本地測試,而androidTest 是功能性測試,在本文屬于單元測試,不需要連接配接具體的模拟器或者真機,單元測試代碼寫在Test檔案夾裡面。
編寫一個簡單的Junit3測試用例
1.選中待測試類中具體的方法。右擊goto—>Test 彈出如下視窗進行簡單操作,就可以生成一個junit3的單元測試。(更改頁籤也可以生成 junit4 的單元測試)
public class MathUtilTest extends TestCase {
public void setUp() throws Exception {
super.setUp();
System.out.print("開始.......\n");
}
public void testAdd() throws Exception {
System.out.print(".testAdd \n");
assertEquals(2, MathUtil.add(1, 1));
}
public void testAdd1() throws Exception {
System.out.print(".testAdd1 \n");
assertEquals(2, MathUtil.add(2, 2));
}
public void tearDown() throws Exception {
System.out.print("結束.......\n");
}
}
1.在Junit3,為了更好的管理項目,建議将測試類放在與源代碼同包名下的目錄下
2.命名建議原類名+TestCase
3.unit3中規定具體運作的測試方法必須要以test開頭,後面的自己另起。于是就有了測試方法test_add()(為了清晰,我個人習慣用下劃線命名規則來命名測試方法)
4.測試 的方法有了,那麼我們根據什麼來判斷這個測試方法是否通過呢,沒錯,就是通過assertEquals(期望值,實際值)方法來進行斷言,由于我們知道1+1肯定等于2,于是我們就斷言如果方法MathUtil.add(1, 1)的結果肯定為2,于是就有了assertEquals(2, MathUtil.add(1, 1));
運作
右擊方法就方法選擇Run->testadd()
6.運作結果,因為實際值與期望值相同是以就通過了
7.當然如果和期望的值不相等就會出現異常情況。
可以看到測試用例結果顯示,一個通過一個沒有通過。沒有通過原因也寫出來了,Expected 值和Actual值不相等。
junit3測試有幾明顯的地方。
1.測試方法必須以test開頭否則無法識别
2.需要繼承TestCase類。
斷言
TestCase類是繼承自Assert,是以預設擁有下面的斷言方法,具體也可以參考源碼(junit.framework.Assert)中支援的斷言方法
setUp&&tearDown
Junit3中TestCase提供了 setUp 和 tearDown方法:
setUp():在每個測試方法之前調用,一般用于初始化
tearDown():在每個測試方法執行完畢之後調用,一般用于資源回收
如果類中存在多個測試方法,那麼測試執行順序為
1.1setUp->
1.2test_測試方法1->
1.3tearDown->
1.4setUp->
1.5test_測試方法2->
1.6tearDown->
4.TestCase
4.1 測試異常
測試的時候遇到異常可以通過在方法後面throws Exception處理,将異常抛出,在最終的測試結果中可以檢視到。
那麼什麼時候需要抛出異常呢?
下面我舉一個場景:
實際開發過程中,我們難免會設計一些方法,這些方法可能會抛出某些指定的異常,需要給上層使用者進行處理,那麼在測試的時候,我們可以将這些指定的異常進行捕捉,然後針對其他異常進行抛出,作為測試結果,測試這些方法是否會有額外的異常出現。
例如下面的例子:
public class MathUtil {
/**
* 從一個浮點型字元串中擷取小數部分的整數
* <p/>
* 實際上如果是一個整數或者其他不是數字的字元串,我們除了抛出無法轉型的異常之外,還可能會抛出數組越界的異常
* 假設是"123",那麼是沒有numbers[1]的
*
* @param str
* @return
* @throws NumberFormatException
*/
public static int getDecimalFromString(String str) throws NumberFormatException {//聲明已經知道的異常
String[] numbers = str.split("\\.");
return Integer.valueOf(numbers[1]);
}
}
測試類
public class MathUtilJunit3TestCase extends TestCase {
public void test_getDecimalFromString() throws Exception {
System.out.println("---Calling test_getDecimalFromString---");
try {
assertEquals(456, MathUtil.getDecimalFromString("123.456"));
assertEquals(0, MathUtil.getDecimalFromString("abc"));
assertEquals(0, MathUtil.getDecimalFromString("123"));
} catch (NumberFormatException e) {
assertNotNull(e.getMessage());
}
}
}
運作結果片段,除了定義的格式異常,還會出現 OutOfBoundsException 等其它提前沒有預料到的異常
經過這個測試能夠過濾已知異常,對未知異常暴露在測試階段。
4.2 測試套件
測試套件說白了就是批量測試。将獨立的測試進行組裝,達到一次測試多個目的。
/**
* @author ywc
* @since 2017-01-13
*/
public class UtilTestSuite extends TestSuite {
public UtilTestSuite() {
super();
addTestSuite(MathUtilTestCase.class);
}
}
通過junit提供的api可以友善的實作。需要注意繼承的父類是TestSuit 而不是單元測試TestCase。
4.3 測試
配置全局初始化和結束
TestSuite可以了解為一個功能單元集合,有時我們希望在測試這個單元功能時,全局初始化一些資源,以及全局回收一些資源(比如:初始化時建立資料庫連接配接,結束時候統一結束連接配接),那麼這個時候,采用TestCase的setUp和tearDown明顯不夠用了(testcase的setup和down是每次運作單個測試方法均會調用)
public class UtilTestSuite extends TestSuite {
public UtilTestSuite() {
super();
addTestSuite(MathUtilTestCase.class);
}
public Test suite() {
addTestSuite(MathUtilTestCase.class);
TestSetup wrapper = new TestSetup(this) {
protected void setUp() {
System.out.println("---Calling Global_setUp---");
}
protected void tearDown() {
System.out.println("---Calling Global_tearDown---");
}
};
return wrapper;
}
如果你進行過實際操作的話,就會發現預設的AndroidSDK中沒有TestSetup類,這是因為Android SDK中僅保留極少部分的Junit3代碼(主要是junit.framework的代碼),其中并沒有我們所用到的TestSetup類
那麼TestSetup類又是從哪裡來的呢,其實在使用的時候,我已經引用了Junit4.12的類庫了