Android應(yīng)用測(cè)試開發(fā)——單元測(cè)試

前言

上一篇文章,我們了解了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(""))
    }
erro.png

對(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。


image.png
使用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)。


image.png
使用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)的介紹。

config.png

類似的國(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è)試代碼吧。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容