1. 程式人生 > >Android測試之裝置化測試(Instrumented Tests)

Android測試之裝置化測試(Instrumented Tests)

當我們需要使用到安卓框架的時候,也就是android.jar裡面的api的時候,使用本地單元測試的方式就難以做到了。這時就要使用裝置化的測試。

裝置化測試分為

——裝置化單元測試(Instrumented Unit Test)

——元件整合測試

——app整合測試。

以下是官網對這幾種測試的特點簡述和詳細說明:

詳細說明:

Type Subtype Description
Unit tests
Local Unit Tests Unit tests that run locally on the Java Virtual Machine (JVM). Use these tests to minimize execution time when your tests have no Android framework dependencies or when you can mock the Android framework dependencies.
Instrumented unit tests Unit tests that run on an Android device or emulator. These tests have access to information, such as the  of the app you are testing. Use these tests when your tests have Android dependencies that mock objects cannot satisfy.
Integration Tests
Components within your app only This type of test verifies that the target app behaves as expected when a user performs a specific action or enters a specific input in its activities. For example, it allows you to check that the target app returns the correct UI output in response to user interactions in the app’s activities. UI testing frameworks like Espressoallow you to programmatically simulate user actions and test complex intra-app user interactions.
Cross-app Components This type of test verifies the correct behavior of interactions between different user apps or between user apps and system apps. For example, you might want to test that your app behaves correctly when the user performs an action in the Android Settings menu. UI testing frameworks that support cross-app interactions, such as UI Automator, allow you to create tests for such scenarios.

裝置化測試的類需要放在module-name/src/androidTests/java/這個目錄下,類名和包名沒有要求,但如果是suite型別的測試類,包名通常用.suite結尾。

對於支援到JUnit4的gradle版本,我們只需要按照junit4的寫法來就可以了,關於這方面,可以參考另一篇博文。

下面講一講各種型別的裝置化測試的基本實現流程:

裝置化單元測試

首先,你需要引入以下依賴:

dependencies {
    androidTestCompile 'com.android.support:support-annotations:24.0.0'
    androidTestCompile 'com.android.support.test:runner:0.5'
    androidTestCompile 'com.android.support.test:rules:0.5'// Optional -- Hamcrest library
    androidTestCompile 'org.hamcrest:hamcrest-library:1.3'// Optional -- UI testing with Espresso
    androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2'// Optional -- UI testing with UI Automator
    androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.1.2'}
如果你其它地方有引用到support-annotations這個包的話,那麼它的版本有可能會跟著幾個包所引用到的annotations包版本衝突,這時候可以把上面第一個引入刪掉,並且對其它幾個包都這樣配置一下(就是去掉它們裡面的這個包的依賴的意思):

androidTestCompile ('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })

然後,你還需要在你當前需要測試的module的build.gradle檔案里加入這個配置:

android {
    defaultConfig {
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"}}

最後是程式碼部分,除了按照junit4的寫法新增方法和註解外,只需要在類上新增一個@RunWith(AndroidJUnit4.class) 這樣的註解。這樣就可以在test方法裡面呼叫安卓api的方法了。

元件整合測試

這個包括Service和ContentProvider的測試,支援程序間的通訊。但不支援IntentService和廣播。

其實Activity的整合測試也屬於這部分,官方介紹時大概為了方便,直接只在app整合測試環節使用了activity的測試。其實也可以放到這裡來,單個引用activity來做測試。

app整合測試部分只是綜合使用了這幾種引用模式。

其實這部分的話,除了上面單元測試的那幾步都要以外,只要再加一個這樣的申明就差不多了:

@Rule
    public ActivityTestRule<OneFlagActivity> mActivityRule = new ActivityTestRule<>(OneFlagActivity.class);//具體可看下面app整合測試的使用。

Service的整合測試跟單個應用內的測試比較相像。只不過把宣告activity變成了宣告service,不過沒在宣告的時候指定具體的service,而是在test方法裡面再做繫結操作。

@RulepublicfinalServiceTestRule mServiceRule =newServiceTestRule();
@Testpublicvoid testWithBoundService()throwsTimeoutException{// Create the service Intent.Intent serviceIntent =newIntent(InstrumentationRegistry.getTargetContext(),LocalService.class);// Data can be passed to the service via the Intent.
    serviceIntent.putExtra(LocalService.SEED_KEY,42L);// Bind the service and grab a reference to the binder.IBinder binder = mServiceRule.bindService(serviceIntent);// Get the reference to the service, or you can call// public methods on the binder directly.LocalService service =((LocalService.LocalBinder) binder).getService();// Verify that the service is working correctly.
    assertThat(service.getRandomInt(),is(any(Integer.class)));}

這裡的mServiceRule就相當於繫結service的那個activity。

App整合測試

這部分的測試是綜合使用了上面的那些測試模式,尤其是activity的,讓你引用activity的輸入,模擬使用者的ui操作。可以是應用內的操作,也可以跨應用操作。

嗯。。

給一段程式碼感受一下:

@Rule
public ActivityTestRule<OneFlagActivity> mActivityRule = new ActivityTestRule<>(OneFlagActivity.class);//該變數起了一個載入activity的作用,
                                                                                            // 不加的話就要在測試方法裡面手動啟動或者新增intent啟動
@Test
public void mockClick(){
    ViewInteraction vi = onView(withId(R.id.tv_textborad));//1.找到ui元件
vi.perform(click());//2.操作
onView(withId(R.id.tv_textborad2)).check(matches(isDisplayed()));//3.判斷結果
}

正如我在註釋裡寫的那樣,就是那麼個作用和操作過程哈。箇中的使用和其它api的使用一兩句話也說不完,只有自己去寫去慢慢摸索了。

關於更詳細的這幾個api的說明也可以看這文件:https://developer.android.com/training/testing/ui-testing/espresso-testing.html

另外,在啟動這個測試前,最好要把開發者選項裡面的關於動畫的幾個選項關閉掉,否則有可能會導致不可預期的錯誤。一般有下面這幾個選項:

1.視窗動畫縮放  2.  過渡動畫縮放  3.動畫程式時長縮放

至於跨應用的操作,限於篇幅,這裡就不展開說了,其配置也是按照上面單元測試的這些就可以了,只是模擬操作的程式碼使用了不同的api。要用到的是UIDevice、UIObject等幾個類。


至此,關於as整合的幾種測試方式就介紹這麼多了。畫了個圖稍微概括一下這幾種方式。