アンドロイドUIAutomatorでUIテスト、最も簡単かつ迅速ガイド

By JS | Last updated: August 15, 2019

UIAutomatorは、AndroidでUIをテストすることができるよう支援するライブラリです。 一般的に、UIをテストするライブラリは以下のように二つあり、それぞれ特徴が異なります。 テストする用途に適したものを使用します。

  • UIAutomator: ブラックボックステストは、二つ以上のアプリを連動してテストするとき良い
  • Espresso: ホワイトボックステストは、一つのエプマンテストするとき良い

この二つの大きな違いで、Espressoは、whiteboxテストです。 テストコードは、自分のアプリのアクティビティを直接呼び出すし、アプリがどのようなインテントを誰に伝えていることを傍受することができていて、アプリの実装がうまくていることをテストすることができます。

逆に、UIAutomatorはブラックボックステストです。 アプリの実装がどうなったかはわかりません。アプリ名にアプリを実行させて、画面がトトをするときいくつかのボタンを押して、ボタンを押したときにどのようなポップアップがトゥヌンジテストすることです。 ユーザーはシナリオを中心にテストコードを記述することです。

テストコードでボタンを押すことができる理由は、画面上のテキスト情報とボタンID情報を読み取ることができるからです。 そのため、二つ以上のアプリを連動してテストするときに使用することができます。 (Espressoの場合、1つのエプマンテストすることができます。)

UIAutomatorを使用してUIをテストする方法を簡単に紹介します。

最新バージョンはUIAutomator2です。最新のライブラリを中心に紹介します。この記事で使用するコードは、すべての鼻間違って作成しました。

プロジェクトの設定

アンドロイドスタジオでプロジェクトを作成してください。アプリを実装した後で、UIAutomatorを利用してテストコードを作成するにはgradleライブラリを追加する必要があります。

以下のようにアプリgradleのdependencyに追加するだけです。私Androidxライブラリを使用しました。 このライブラリは、Junitで動作するので junitandroidx.test:runnerは当然追加されている必要があります。

dependencies {
  testImplementation 'junit:junit:4.12'
  androidTestImplementation 'androidx.test:runner:1.2.0'
  androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.2.0'
  ....
}

テストコードの作成

アプリを実装した場合はこれでテストコードを作成する必要があります。

テストコードは、プロジェクトの ../app/src/androidTest/のInstrumentedTestファイルに作成する必要があります。(Unit testに作成すると、ありません。)

上記のようにUIAutomatorはブラックボクシングのテストです。 まるで目で画面を見てボタンをタッチしたり、任意のテキストが見えるテストするのと同じです。 このように人が行うことを自動化することです。

私たちは、このようなシナリオをUIAutomatorを利用して、コードにオームギョヤます。

アプリを実行する

まず、Homeボタンを押して、私のアプリを起動させることをコードで作成されます。 ここUIAutomatorの UiDeviceUntilByクラスを使用します。 おおよその使用方法を知っている、詳細は後で説明します。

@Test
fun testRunMyApp() {
    // Initialize UiDevice instance
    val device = UiDevice.getInstance(
        InstrumentationRegistry.getInstrumentation());    // 1

    // Press home button
    device.pressHome()  // 2

    // Wait for launcher
    val launcherPackage = device.launcherPackageName    // 3
    assertThat(launcherPackage, notNullValue())
    device.wait(
        Until.hasObject(By.pkg(launcherPackage), 5000
    )   // 4


    // Launch my app
    val context = InstrumentationRegistry.getTargetContext()
    val intent = context.packageManager
            .getLaunchIntentForPackage(context.packageName)!!
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
    context.startActivity(intent)   // 5

    // Wait for the app to appear
    device.wait(
        Until.hasObject(By.pkg(context.packageName)), 5000
    )   // 6
}

'// 1'ようなことは、番号で表示し、以下の説明しました。

  1. UiDeviceは、デバイス情報にアクセスすることができるオブジェクトです。 Home、Backボタンを押すか、または特定の座標をタッチすることができます。

またはデバイスをwakeUp、sleep状態にすることができます。 2. Homeボタンを押して、Launcherに移動します。 3. launcherPackageNameは基本的に設定されたLauncherの名前を取得します。 4. waitはどのような状況を待ちます。このコードは、Launcherが実行されるまで待ちます。 timeoutは5000msに設定しました。 5. 私のアプリのパッケージ名でインテントを作って実行します。 6. 私のアプリが実行されるまで待ちます。

By(セレクタ)

上記のLauncherまたはマイアプリを見つける Byクラスを使用していました。

Byはパッケージ、クラス、リソースID、リソースのプロパティなどでアプリのコンポーネントの検索に使用します。 Byは検索しようとするオブジェクトの情報を含んでいるBySelectorオブジェクトを返し、これで対象が何なのか探すのに使用します。

たとえば、次のコードでは By.pkgは、YouTubeアプリのBySelectorを返します。

By.pkg("com.android.youtube")
  • By.pkg: 引数として渡されたパッケージに該当するBySelectorリターン
  • By.text: 画面に表示されるテキストの引数として渡されたtextに対応するオブジェクトのBySelectorリターン
  • By.clazz: クラス名でオブジェクトを探して、そのオブジェクトのBySelectorを返し
  • By.res: リソースIDでオブジェクトを探して、そのオブジェクトのBySelectorを返し

などなど、他にも多くのAPIを提供します。

Byが提供するより多くのメソッドは、By referenceを参照してください。

Until

Untilクラスは UiObject2Conditionオブジェクトを返してくれるファクトリクラスです。 UiObject2Conditionは、次のコードのように、wait()の引数として使用され、どのような状況を表現するオブジェクトです。 Until.hasObjectは、現在のデバイスが引数として受け取ったBySelectorの条件を満たしているかどうかチェックするためのコードです。

device.wait(
    Until.hasObject(By.pkg(launcherPackage)), 5000
)

まとめると、Untilはどのような状況を表現するUiObject2Conditionオブジェクトを作成してくれて、このオブジェクトは、waitなどと一緒に使用されます。

Untilは次のようにいくつかのメソッドを提供します。

  • Until.hasObject(BySelector selector): デバイスの要素の中で引数として渡されたセレクタの条件を満たしている要素が1つでもあることを
  • Until.longClickable(boolean isLongClickable): ロングクリックが可能な要素があるか
  • Until.scrollFinished(Direction direction): スクロールが終わったか
  • Until.textEquals(String text): 引数として渡されたテキストと一致するテキストが画面にいるかどうか

Utilが提供する、より多くのメソッドは、Until referenceを参照してください。

ボタンを探して、クリックして、ポップアップを確認する

今までのアプリを実行する方法を説明しました。 その過程でUI要素を意味する BySelectorとどのような状況の条件を表現するUiObject2Conditionの概念について説明しました。 Selectorを使用すると、画面に浮かんでいるUIを見つけることができます。

サンプルでOKボタンを押すと、Dialogが開いたままに、OKボタンを押すと、Dialogが終了したアプリを作成しました。 サンプルアプリのソースは、GitHubにあります。

アプリを起動すればOKとCANCELボタンがあり、OKをクリックすると、以下のようにDialogが表示されます。 sample-app

次のコードは、アプリで[OK]ボタンをクリックし、Dialogが浮かぶことを待ってから再度OKボタンを押すテストコードです。 もし途中でViewがないか、実行されない場合Assertが発生して、テストは失敗します。

@Test
fun testButtonDialog() {
    // Launch and wait for the app
    val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
    val context = InstrumentationRegistry.getTargetContext()
    val intent = context.packageManager
        .getLaunchIntentForPackage(context.packageName)!!
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
    context.startActivity(intent)
    device.wait(
        Until.hasObject(By.pkg(context.packageName).depth(0)),
        5000
    )

    // Find and click OK button
    val okButton: UiObject2 = device.findObject(
        By.text("OK").clazz("android.widget.Button")
    )   // 1
    if (okButton.isEnabled && okButton.isClickable) {
        okButton.click()
    }   // 2

    // Wait for the dialog
    val dlgTitleSelector: BySelector = By.text("My Dialog")   // 3
    device.wait(Until.hasObject(dlgTitleSelector), 1000)    // 4

    val dlgTitle: UiObject2 = device.findObject(
        dlgTitleSelector
    )   // 5
    val dlgDescription: UiObject2 = device.findObject(
        By.text("we are testing with UIAutomator")
    )   // 6

    // Click OK button
    val dlgButton: UiObject2 = device.findObject(
        By.text("OK")
    )   // 7
    dlgButton.click()
}
  1. アプリで「OK」のテキストを検索します。
  2. 1で得られたUiObject2オブジェクトがクリック可能であればクリックします。
  3. 2のために実行されるDialogのTitleタイトルSelectorを作成します。
  4. 3のSelectorでDialogが庭まで待ちます。
  5. Dialogが実行された後、titleのUiObject2を検索します。ここで追加で何かをしないです。
  6. Dialogが実行された後、descriptionのUiObject2を検索します。ここで追加で何かをしないです。
  7. Dialogの[OK]ボタンのUiObject2を探して、クリックします。その後、Dialogは終了し、テストも終了します。

この過程で、オブジェクトが見つからない場合、テストは失敗し処理されます。

Selectorを作成するときにtextに設定すると、コードを実装するのは簡単。 しかし、テキストが変更されたとき、テストコードも変更する必要がありますので変わらない属性でSelectorを作ることをお勧め。

たとえば、多言語をサポートしているアプリであれば、テキストは言語によって異なります。またはUIが変更され、テキストも一緒に変更されることがあります。 ViewのリソースIDが変更されない場合、これを利用することがより良いことができます。

まとめ

UIAutomator2の基礎的な使用方法を説明しました。この程度なら簡単なテストコードを書くことができます。 テストコードの作成中に他の機能が必要か、より詳細なことを知るならUIAutomator Referenceや他のチュートリアルを見て学習ください。

参考

Related Posts

codechachaCopyright ©2019 codechacha