前言
上一篇文章,我們了解了Android測(cè)試app的一些框架,這一篇我們來(lái)構(gòu)建出我們的單元測(cè)試。
構(gòu)建本地單元測(cè)試
添加依賴
build.gradle的依賴中添加junit4框架和mockito框架
dependencies {
// Required -- JUnit 4 framework
testCompile 'junit:junit:4.12'
// Optional -- Mockito framework
testCompile 'org.mockito:mockito-core:1.10.19'
}
JUnit不必多說(shuō)是單元測(cè)試框架,mockito是java最流行的mock框架。由于本地的單元測(cè)試環(huán)境中并沒(méi)有實(shí)際運(yùn)行的Android的環(huán)境,所以對(duì)于一些單測(cè)用例我們是需要這個(gè)環(huán)境的,但是用真機(jī)測(cè)試效率又太低,因此引入mock來(lái)模擬這個(gè)環(huán)境。
JUnit的使用
JUnit4比JUnit3更簡(jiǎn)潔,不需要集成TestCase類,方法名也不需加“test”前綴。我們是@Test注解來(lái)標(biāo)記要測(cè)試的方法。
class ExampleUnitTest {
@Test
@Throws(Exception::class)
fun addition_isCorrect() {
assertEquals(4, AppUtils().addNumber(2, 2))
}
}
class AppUtils{
fun addNumber(a : Int, b : Int) = a + b
}
我們可以寫多個(gè)用例來(lái)測(cè)試我們的代碼。JUnit還有其他的注解來(lái)滿足我們的測(cè)試用例編寫。具體的使用可以看這里JUni最新api。這里不再介紹。有機(jī)會(huì)再寫一篇關(guān)于JUnit實(shí)戰(zhàn)的一些技巧。
Not Mocked
JUnit的android插件下運(yùn)行的是android.jar實(shí)際上不包含任何實(shí)際的代碼,因此是不能直接使用的。如果直接使用,例如是用TestUtils的方法。結(jié)果會(huì)拋出not mocked的錯(cuò)誤。
@Test
fun androidCodeTest() {
assert(TextUtils.isEmpty(""))
}

對(duì)于這類的方法,最好的方案是重新寫一個(gè)自己的TextUtils,使用自己的方法?;蛘邷y(cè)試用例不使用和android相關(guān)的代碼。當(dāng)然也是有繞過(guò)這個(gè)錯(cuò)誤的。
android{
...
testOptions {
unitTests.returnDefaultValues = true
}
}
不過(guò)最好不要這樣做,這樣會(huì)導(dǎo)致所有的這種類型都會(huì)返回默認(rèn)值。TextUtils.isEmpty("haha")返回的結(jié)果也是true。

使用mockito
1、需要配置mock框架,我們已經(jīng)配置了。
2、測(cè)試類上加上RunWith的注解
3、要mock的對(duì)象加上@Mock注解
4、實(shí)際使用Mock的對(duì)象方法,需要替換返回值
@RunWith(MockitoJUnitRunner::class)
class ExampleUnitTest {
private val FAKE_STRING = "TestDemo"
@Mock
internal var mMockContext: Context? = null
@Test
fun mockTest() {
`when`(mMockContext!!.getString(R.string.app_name))
.thenReturn(FAKE_STRING)
val result = mMockContext!!.getString(R.string.app_name)
assertEquals(result, FAKE_STRING)
}
實(shí)際上本地的單元測(cè)試如果要用android相關(guān)的代碼或者android環(huán)境下的數(shù)據(jù)是不可以的,我們?nèi)钥梢詍ock出一個(gè)模擬的環(huán)境來(lái)達(dá)到自己的測(cè)試目的。
進(jìn)一步的了解mockito,可以看官方文檔。
構(gòu)建設(shè)備單元測(cè)試
先配置好環(huán)境,添加需要的依賴。
android{
defaultConfig{
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
}
dependencies {
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
}
使用test包下提供的各種方法獲取當(dāng)前的運(yùn)行的環(huán)境等。例子中是獲取了application的context,來(lái)獲取app的包名。
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() throws Exception {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getTargetContext();
assertEquals("com.example.administrator.testdemo", appContext.getPackageName());
}
}
然后點(diǎn)擊運(yùn)行到具體的設(shè)備上。最終綠橋通過(guò)。
創(chuàng)建測(cè)試套件
理解為測(cè)試的集合,可以將多個(gè)測(cè)試類集合到一起,運(yùn)行這個(gè)套件即可。
@RunWith(Suite::class)
@Suite.SuiteClasses(ExampleInstrumentedTest::class, ExampleInstrumentedTest2::class)
class UnitTestSuite {
}
在兩段測(cè)試代碼中添加:System.out.println("test1")和System.out.println("test2")代碼,最終運(yùn)行這個(gè)套件,兩段代碼均被打印了出來(lái)。

使用Firebase Test Lab
Firebase是谷歌的測(cè)試實(shí)驗(yàn)室,使用的是google的數(shù)據(jù)中心內(nèi)托管的設(shè)備。就是遠(yuǎn)程使用google的設(shè)備測(cè)試。谷歌的設(shè)備齊全,尺寸的兼容性,設(shè)備的兼容性都可以測(cè)出來(lái)。其實(shí)就是遠(yuǎn)程租用的模式。當(dāng)然需要注冊(cè)賬號(hào),配置應(yīng)用,具體的使用可以去看官網(wǎng)的介紹。

類似的國(guó)內(nèi)也有很多平臺(tái),不過(guò)google使用起來(lái)的很方便直接在android studio即可配置,比較方便。而且可以免費(fèi)使用(不過(guò)有一些限制)。想用嗎?前提是你需要科學(xué)上網(wǎng)。
后記
學(xué)會(huì)了怎么構(gòu)建單測(cè)了,我們就開始在自己的項(xiàng)目中添加測(cè)試代碼吧。