下面介紹一下如何使用 junit框架。JUnit(https://junit.org/junit5/) 是一個(gè)很著名的java 單元測試框架雷绢。由于是基于針對java 做測試的,所以是沒有android 環(huán)境的儡炼,當(dāng)然 android 中的一些工具類也是不能使用的芒帕,比如TextUtils(android.text.TextUtils)這個(gè)類。
http://d.android.com/tools/testing
https://developer.android.com/training/testing/fundamentals
demo 示例介紹
新建項(xiàng)目
用android studio
新建的 android
項(xiàng)目默認(rèn)自帶 java unitTest
和 android
的相關(guān)單元測試框架敲茄。
如果沒有我們可以在項(xiàng)目的gradle
文件中剛添加
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
上面三行代碼 testImplementation 'junit:junit:4.12’
是用來添 junit
下面的兩個(gè)代碼是用來添加 runner
和 espresso
框架位谋。
由于沒有 android
環(huán)境的類,所以JUnit 比較適合做純java的基本類方法的單元測試堰燎。
首先來看一個(gè) android studio
創(chuàng)建的項(xiàng)目自帶的一個(gè)單元測試代碼掏父,來看看 JUnit 是如何使用的。 在項(xiàng)目中找到ExampleUnitTest
這個(gè)類秆剪,位置在
Project 模式下 模塊名稱/src/test/java/{項(xiàng)目包路徑}/ExampleUnitTest.java
如圖所示:
在Project 視圖或 Android 視圖中測試文件的所在位置
ExampleUnitTest.java 這個(gè)文件的代碼如下:
package cn.com.qianli.demoforunittest;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Example local unit test, which will execute on the development machine (host).
*
* @see <a href="[http://d.android.com/tools/testing](http://d.android.com/tools/testing)">Testing documentation</a>
*/
public class ExampleUnitTest {
@Test public void addition_isCorrect() throws Exception {
assertEquals(4, 2 + 2);
}
}
可以看到代碼還是比較簡單的赊淑,要說明的就是 @Test 是junitTest 框架中的 annotation。
我們進(jìn)入到Junit的代碼中看一下
/**
* Asserts that two longs are equal. If they are not, an
* {@link AssertionError} is thrown.
*
* @param expected expected long value.
* @param actual actual long value
*/
static public void assertEquals(long expected, long actual) {
assertEquals(null, expected, actual);
}
/**
* Asserts that two longs are equal. If they are not, an
* {@link AssertionError} is thrown with the given message.
*
* @param message the identifying message for the {@link AssertionError} (<code>null</code>
* okay)
* @param expected long expected value.
* @param actual long actual value
*/
static public void assertEquals(String message, long expected, long actual) {
if (expected != actual) {
failNotEquals(message, Long.valueOf(expected), Long.valueOf(actual));
}
}
其實(shí)仅讽,assertEquals方法是 org.junit中 Assert這個(gè)類下的一系列重載方法陶缺。如下:
當(dāng)然 Assert這個(gè)類還有其他方法:
我們在自己編寫單元測試代碼的時(shí)候可以根據(jù)情況使用合適的方法做效驗(yàn)。
我們來執(zhí)行 ExampleUnitTest 看看效果洁灵。在文件上右擊鼠標(biāo)饱岸,出現(xiàn)下面這樣的彈出框。
可以看到3個(gè)運(yùn)行選項(xiàng)徽千。
第一個(gè) :Run ‘ExampleUnitTest’
這個(gè)直接運(yùn)行測試用例苫费,看結(jié)果的。
第二個(gè):Debug ‘ExampleUnitTest’
運(yùn)行這個(gè)是可以直接進(jìn)行debug的双抽,方式和我們debug android代碼類似百框。
第三個(gè):
Run ‘ExampleUnitTest’ with Coverage
https://www.jetbrains.com/help/idea/running-test-with-coverage.html
這里我們運(yùn)行第一個(gè) Run ‘ExampleUnitTest’ 可以看到結(jié)果如下。
順便說明牍汹,如果你在右擊的時(shí)候是在某一個(gè)方法上右擊的铐维,那么執(zhí)行的是只是某一個(gè)方法內(nèi)的測試代碼。
如果右擊的時(shí)候不再任何方法內(nèi)慎菲,那么執(zhí)行的是這個(gè)測試用例文件中所有的測試方法嫁蛇。
還可以通過界面上的快捷方式來執(zhí)行測試用例。
1 的小圖標(biāo)點(diǎn)擊后是執(zhí)行 ExampleUnitTest中所有的測試case露该, 2 則是執(zhí)行addition_isCorrect 單個(gè)方法的用例棠众。
3處雙擊和2的效果一樣,執(zhí)行的是addition_isCorrect 單個(gè)方法的用例。
寫一個(gè)自己的測試用例
下面我們用一個(gè)具體的真實(shí)業(yè)務(wù)例子說明一下闸拿,在真實(shí)項(xiàng)目中測試用例的使用情況空盼。
比如,我們需要寫一個(gè)簡單的字符處理新荤。
需要將電話號碼或者銀行卡號按照 344 的格式顯示揽趾,比如 13512341234 顯示為 135 1234 1234 。銀行卡號也顯示為每4為一個(gè)間隔顯示苛骨。
我們二話不說寫一個(gè)方法簽名:
public static String toPhoneGapString(){
return ""
}
沒有任何實(shí)現(xiàn)篱瞎,這個(gè)時(shí)候在方法簽名上右擊,
選擇Create New Test…
出現(xiàn)的對話框勾選需要?jiǎng)?chuàng)建的方法痒芝,我們勾選 toPhoneGapString():String
點(diǎn)擊Ok
出現(xiàn)一個(gè)對話框讓選擇目錄俐筋,我們這個(gè)方法是一個(gè)基本的java方法,所以我們選擇test目錄下的這個(gè)目錄严衬。
就可以看到有一個(gè)新的測試用例文件生成:
寫一行簡單的測試用例代碼澄者,運(yùn)行試試看。
我們的實(shí)現(xiàn)是空的请琳,這里當(dāng)然不可能符合預(yù)期粱挡。這個(gè)時(shí)候我們需要改進(jìn)修改我們的方法toPhoneGapString
。
給方法簽名加入?yún)?shù) String inputStr
具體實(shí)現(xiàn)一段代碼如下:
public static String toPhoneGapString(String inputStr) {
if (inputStr == null) {
return "";
}
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < inputStr.length();i++) {
stringBuilder.append(inputStr.charAt(i));
if((i + 1) % 4 == 3 && (i + 1) != inputStr.length()){
stringBuilder.append(' ');
}
}
return stringBuilder.toString();
}
對我們的單元測試case也做一下修改俄精,這個(gè)時(shí)候我們再次執(zhí)行單元測試文件询筏。
就可以看到舒心的綠色pass了。(話說竖慧,綠色為什么會舒心呢嫌套?)
我們再加上更多的測試用例,如下:
電話號碼多一位圾旨,以 3 4 4 1 的格式輸出灌危,也就是輸出多一個(gè)空格和多出來的數(shù)字。
電話號碼少一位碳胳,以 3 4 2 的格式輸出,
電話號碼中多空格沫勿,希望輸出正常的分割電話號碼
基于這樣的case 我們寫單元測試代碼
assertEquals("135 1234 1234 2", StringUtil.toPhoneGapString("135123412342"));
assertEquals("135 1234 123", StringUtil.toPhoneGapString("1351234123"));
assertEquals("135 1234 1234", StringUtil.toPhoneGapString("135123412 3 4"));
再次執(zhí)行挨约。
發(fā)現(xiàn)最后一個(gè)case 并沒有通過。
這個(gè)時(shí)候就是我們寫代碼的時(shí)候了产雹,修改方法诫惭,知道通過這個(gè)case位置。
只要我們在測試用例中覆蓋了所有的case蔓挖,并且保證運(yùn)行通過夕土,那么我們的小方法就是經(jīng)過測試的。
作為開發(fā)人員也就更加胸有成竹,而不是盲目自信怨绣,迷之自信了角溃。