2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Espressoを用いたUIテストで、指定のViewが表示されるまで待機する

Posted at

背景

これまで、EspressoのUIテストにおけるネットワーク通信待機処理をThread.sleep()で行なっていました。
この方法では、通信が完了した後も指定した時間待つことになり、テスト実行に余計な時間が掛かってしまいます。
これを改善するために、今回はUiAutomatorを利用して指定したViewが表示されたタイミングで待機処理を終了する実装に置き換えました。

実装

まずは、UiAutomatorの依存関係を追加します。

build.gradle
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.uiautomator:uiautomator-v18:2.1.3'

そして、Kotlinの拡張関数を用いてトップレベル関数として待機処理を実装します。
テスト設計にはPageObjectパターンを適用しているため、戻り値にはthisを指定してレシーバを返すようにしています。
※PageObjectパターンはDroidKaigi2019のこちらのセッションを参考にさせていただきました。(https://droidkaigi.jp/2019/timetable/70791/

PageObjectExt.kt
/**
 * [resId]に指定したViewが表示されるまで待つ
 * [timeout]はデフォルトで7秒
 */
fun <T : Any> T.waitShown(resources: Resources, @IdRes resId: Int, timeout: Long = 7_000): T {
    UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
            .wait(Until.findObject(By.res(
                    "[YOUR_APP_PACKAGE_NAME]",
                    resources.getResourceEntryName(resId))),
                    timeout)
    return this
}

テストメソッドで使うとこのようになります。
画面の挙動としては、SampleActivityで通信を行い、通信中はローディングが表示され、通信完了後にtarget_viewが表示されるイメージです。

SampleActivityTest.kt
@RunWith(AndroidJUnit4::class)
@LargeTest
class SampleActivityTest {
    @Rule
    @JvmField
    val activityRule: ActivityTestRule<SampleActivity> = ActivityTestRule(SampleActivity::class.java)

    @Test
    fun test() {
        val resources = activityRule.activity.resources

        SampleActivityPage
                .fetchData() // 時間の掛かる通信処理
                .waitShown(resources, R.id.target_view) // `target_view`が表示されるまで待機
                .assert() // 任意のアサーション
    }
}

解説

waitShownの処理を分解して見てみます。

PageObjectExt.kt
/**
 * [resId]に指定したViewが表示されるまで待つ
 * [timeout]はデフォルトで7秒
 */
fun <T : Any> T.waitShown(resources: Resources, @IdRes resId: Int, timeout: Long = 7_000): T {
    // デバイスの状態を提供するクラス。ホームボタンなどの制御も可能。
    val uiDevice: UiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())

    // UI要素を指定するクラス。パッケージ名とリソースID名で指定する。
    val bySelector: BySelector = By.res("[YOUR_APP_PACKAGE_NAME]", resources.getResourceEntryName(resId))

    // waitメソッドに渡す条件。最初に一致するUI要素(BySelector)を条件として返す。
    val searchCondition: SearchCondition<UiObject2> = Until.findObject(bySelector)

    // 条件(SearchCondition)に一致するか、タイムアウトになるまで待機する。
    uiDevice.wait(searchCondition, timeout)

    return this
}
2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?