UI Automator は、アプリ間の機能 UI に適した UI テスト フレームワークです
システムやインストール済みのアプリをテストできます。UI Automator API を使用すると
どの Activity
が含まれるかにかかわらず、デバイス上で可視要素を含む
[設定] メニューを開くなどの操作ができるようになります。
またはテストデバイスのアプリ ランチャーで確認できます。テストで UI コンポーネントを検索するには、
コンポーネントに表示されるテキストやそのコンポーネントに
作成します。
UI Automator テスト フレームワークはインストルメンテーション ベースの API であり、
AndroidJUnitRunner
テストランナーを使用します。文章を書くのに
不透明なボックススタイルの自動テスト。テストコードは内部の
ターゲット アプリの実装の詳細。
UI Automator テスト フレームワークの主要な機能は次のとおりです。
- 状態情報を取得してターゲットでオペレーションを行うための API できます。詳しくは、デバイスの状態にアクセスするをご覧ください。
- 複数のアプリにまたがる UI テストをサポートする API。詳しくは、管理画面 Automator API をご覧ください。
デバイスの状態にアクセスする
UI Automator テスト フレームワークには、アクセスするための UiDevice
クラスが用意されています。
ターゲット アプリが実行されているデバイスで操作を実行できます。Google Chat では
そのメソッドを呼び出して、デバイスのプロパティ(画面の向き、
指定します。UiDevice
クラスでは、次のこともできます。
アクション:
- デバイスの回転を変更する。
- ハードウェア キー(「音量大」など)を押す。
- 「戻る」ボタン、ホームボタン、メニューボタンをクリックする。
- 通知シェードを開く。
- 現在のウィンドウのスクリーンショットを撮る。
たとえば、ホームボタンの押下をシミュレートするには、UiDevice.pressHome()
を呼び出します。
メソッドを呼び出します。
UI Automator API
UI Automator API を使用すると、知識がなくても堅牢なテストを作成できる (ターゲットにしているアプリの実装の詳細)次を使用: 以下の API を使用して、複数のアプリにわたって UI コンポーネントをキャプチャして操作します。
UiObject2
: デバイスに表示される UI 要素を表します。BySelector
: UI 要素のマッチング条件を指定します。By
: 簡潔な方法でBySelector
を作成します。Configurator
: UI Automator テストを実行するための主要なパラメータを設定できます。
たとえば、次のコードは、実行するテスト スクリプトを デバイスで Gmail アプリを開く
Kotlin
device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) device.pressHome() val gmail: UiObject2 = device.findObject(By.text("Gmail")) // Perform a click and wait until the app is opened. val opened: Boolean = gmail.clickAndWait(Until.newWindow(), 3000) assertThat(opened).isTrue()
Java
device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()); device.pressHome(); UiObject2 gmail = device.findObject(By.text("Gmail")); // Perform a click and wait until the app is opened. Boolean opened = gmail.clickAndWait(Until.newWindow(), 3000); assertTrue(opened);
UI Automator をセットアップする
UI Automator で UI テストを作成する前に、必ずテストを構成してください ソースコードの場所とプロジェクトの依存関係(プロジェクトの設定 AndroidX Test のテストをご覧ください。
Android アプリ モジュールの build.gradle
ファイルで、依存関係を設定する必要があります。
UI Automator ライブラリを参照できます。
Kotlin
dependencies {
...
androidTestImplementation('androidx.test.uiautomator:uiautomator:2.3.0-alpha03')
}
Groovy
dependencies {
...
androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.3.0-alpha03'
}
UI Automator のテストを最適化するには、まずターゲット アプリの UI コンポーネントを作成し、それらがアクセス可能であることを確認します。これらの最適化のヒントは 次の 2 つのセクションで説明します。
デバイス上の UI を検査する
テストを設計する前に、
できます。UI Automator テストでこれらのコンポーネントにアクセスできるようにするには、
これらのコンポーネントに、表示されるテキストラベル
android:contentDescription
の値、またはその両方)。
uiautomatorviewer
ツールは、検査に役立つ便利なビジュアル インターフェースを備えています。
表示される UI コンポーネントのプロパティを表示する
アプリが起動します。この情報により
UI Automator を使用してきめ細かいテストを行えます。たとえば UI セレクタを作成し
一致します
uiautomatorviewer
ツールを起動するには:
- 物理デバイスでターゲット アプリを起動します。
- デバイスを開発マシンに接続します。
- ターミナル ウィンドウを開いて、
<android-sdk>/tools/
ディレクトリに移動します。 - 次のコマンドを使用してツールを実行します。
$ uiautomatorviewer
アプリの UI プロパティを表示するには:
uiautomatorviewer
インターフェースで、[Device Screenshot] ボタンをクリックします。- 左側のパネルのスナップショットにカーソルを合わせると、UI コンポーネントが表示されます。
uiautomatorviewer
ツールによって識別される API。プロパティは、 下回っています レイアウト階層が表示されます。 - 必要に応じて、[Toggle NAF Nodes] ボタンをクリックして UI コンポーネントを表示 UI Automator がアクセスできない リソースを定義できます限られた情報しか これらのコンポーネントで使用できます。
Android が提供する UI コンポーネントの一般的なタイプについては、ユーザー インターフェースをご覧ください。
アクティビティのユーザー補助機能を確認する
UI Automator テスト フレームワークは、実装したアプリでより優れたパフォーマンスを発揮します。
Android のユーザー補助機能。View
タイプの UI 要素を使用する場合、または
のサブクラス(SDK の View
のサブクラス)を使用すると、ユーザー補助を実装する必要が
これらのクラスでは、すでにそのように行われています。
一部のアプリでは、より豊かなユーザー エクスペリエンスを提供するためにカスタム UI 要素を使用しています。
そのような要素は、自動的にはユーザー補助サポートを提供しません。アプリが
SDK 以外の View
のサブクラスのインスタンスが含まれるため、
これらの要素にユーザー補助機能を追加するには、
手順は次のとおりです。
- ExploreByTouchHelper を拡張する具象クラスを作成します。
- 新しいクラスのインスタンスを特定のカスタム UI 要素に関連付ける setAccessibilityDelegate() の呼び出し
カスタムビューにユーザー補助機能を追加する方法について詳しくは、 アクセシビリティ対応のカスタムビューの作成をご覧ください。詳細情報 Android でのユーザー補助に関する一般的なベスト プラクティスについては、アプリの利便性を高める アクセス可能。
UI Automator テストクラスを作成する
UI Automator テストクラスは JUnit 4 テストと同じ方法で記述する必要があります クラスです。JUnit 4 テストクラスの作成と JUnit 4 の使用方法の詳細 アサーションとアノテーションについては、インストルメンテーション 単体テストクラスを作成するをご覧ください。
テストの先頭に @RunWith(AndroidJUnit4.class) アノテーションを追加する クラス定義をご覧ください。AndroidJUnitRunner クラスも指定する必要があります。 AndroidX Test で提供されています。このステップは 詳しくは、デバイスまたはエミュレータで UI Automator テストを実行するをご覧ください。
UI Automator テストクラスに、次のプログラミング モデルを実装します。
- 以下を呼び出して、テストするデバイスにアクセスするための
UiDevice
オブジェクトを取得します。 getInstance() メソッドを実行し、Instrumentation オブジェクトとして 渡します。 - 画面に表示される UI コンポーネントにアクセスするための
UiObject2
オブジェクトを取得します。 (たとえば、フォアグラウンドの現在のビューなど)に findObject() メソッド。 - その UI コンポーネントで実行する特定のユーザー操作をシミュレートします。手順は次のとおりです。
UiObject2
メソッドを呼び出す。たとえば、 スクロールするには scrollUntil()、テキスト フィールドを編集するには setText() を使用します。 ステップ 2 と 3 で API を呼び出すことができます。 複雑なユーザー操作をテストするために、必要に応じて繰り返しテストし、 複数の UI コンポーネントや一連の ユーザーアクションで構成されます - このようなユーザーのその後の UI が、想定される状態や動作を反映していることを確認する 行います。
上記の手順については、以降のセクションで詳しく説明します。
UI コンポーネントにアクセスする
UiDevice
オブジェクトは、
確認します。テストでは、UiDevice
メソッドを呼び出して
現在の向きやディスプレイ サイズなど、さまざまなプロパティの状態。
テストでは、UiDevice
オブジェクトを使用して、デバイスレベルのアクションを実行できます。
たとえば、デバイスを特定の回転状態にする、D-pad ハードウェアを押す、
[ホーム] ボタンや [メニュー] ボタンを押すなどの操作を行えます。
デバイスのホーム画面からテストを始めることをおすすめします。最低料金 ホーム画面(またはデバイスで選択したその他の開始位置) UI Automator API に用意されたメソッドを呼び出して、 特定の UI 要素でトレーニングできます
次のコード スニペットは、テストで
UiDevice
を実行し、ホームボタンの押下をシミュレートします。
Kotlin
import org.junit.Before import androidx.test.runner.AndroidJUnit4 import androidx.test.uiautomator.UiDevice import androidx.test.uiautomator.By import androidx.test.uiautomator.Until ... private const val BASIC_SAMPLE_PACKAGE = "com.example.android.testing.uiautomator.BasicSample" private const val LAUNCH_TIMEOUT = 5000L private const val STRING_TO_BE_TYPED = "UiAutomator" @RunWith(AndroidJUnit4::class) @SdkSuppress(minSdkVersion = 18) class ChangeTextBehaviorTest2 { private lateinit var device: UiDevice @Before fun startMainActivityFromHomeScreen() { // Initialize UiDevice instance device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) // Start from the home screen device.pressHome() // Wait for launcher val launcherPackage: String = device.launcherPackageName assertThat(launcherPackage, notNullValue()) device.wait( Until.hasObject(By.pkg(launcherPackage).depth(0)), LAUNCH_TIMEOUT ) // Launch the app val context = ApplicationProvider.getApplicationContext<Context>() val intent = context.packageManager.getLaunchIntentForPackage( BASIC_SAMPLE_PACKAGE).apply { // Clear out any previous instances addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK) } context.startActivity(intent) // Wait for the app to appear device.wait( Until.hasObject(By.pkg(BASIC_SAMPLE_PACKAGE).depth(0)), LAUNCH_TIMEOUT ) } }
Java
import org.junit.Before; import androidx.test.runner.AndroidJUnit4; import androidx.test.uiautomator.UiDevice; import androidx.test.uiautomator.By; import androidx.test.uiautomator.Until; ... @RunWith(AndroidJUnit4.class) @SdkSuppress(minSdkVersion = 18) public class ChangeTextBehaviorTest { private static final String BASIC_SAMPLE_PACKAGE = "com.example.android.testing.uiautomator.BasicSample"; private static final int LAUNCH_TIMEOUT = 5000; private static final String STRING_TO_BE_TYPED = "UiAutomator"; private UiDevice device; @Before public void startMainActivityFromHomeScreen() { // Initialize UiDevice instance device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()); // Start from the home screen device.pressHome(); // Wait for launcher final String launcherPackage = device.getLauncherPackageName(); assertThat(launcherPackage, notNullValue()); device.wait(Until.hasObject(By.pkg(launcherPackage).depth(0)), LAUNCH_TIMEOUT); // Launch the app Context context = ApplicationProvider.getApplicationContext(); final Intent intent = context.getPackageManager() .getLaunchIntentForPackage(BASIC_SAMPLE_PACKAGE); // Clear out any previous instances intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); context.startActivity(intent); // Wait for the app to appear device.wait(Until.hasObject(By.pkg(BASIC_SAMPLE_PACKAGE).depth(0)), LAUNCH_TIMEOUT); } }
この例では、@SdkSuppress(minSdkVersion = 18) ステートメントにより、 Android 4.3(API レベル 18)以上を搭載したデバイスでのみテストが実行されるようにすること。 UI Automator のフレームワークで必要な いくつかのリソースが用意されています
findObject()
メソッドを使用して、データを表す UiObject2
を取得します。
ビューを返します。UiObject2
は再利用できます。
作成したインスタンスを必要に応じて追加してみます。
なお、UI Automator テスト フレームワークは、現在のディスプレイで
テストが UiObject2
インスタンスを使用して UI をクリックするたびに一致します。
プロパティのクエリを実行できます
次のスニペットは、テストで UiObject2
を構築する方法を示しています。
アプリの [Cancel] ボタンと [OK] ボタンを表すインスタンス。
Kotlin
val okButton: UiObject2 = device.findObject( By.text("OK").clazz("android.widget.Button") ) // Simulate a user-click on the OK button, if found. if (okButton != null) { okButton.click() }
Java
UiObject2 okButton = device.findObject( By.text("OK").clazz("android.widget.Button") ); // Simulate a user-click on the OK button, if found. if (okButton != null) { okButton.click(); }
セレクタを指定する
アプリの特定の UI コンポーネントにアクセスするには、
By
クラスを使用して BySelector
インスタンスを作成します。BySelector
は、表示された UI の特定の要素に対するクエリを表します。
一致する要素が複数見つかった場合は、
レイアウト階層がターゲット UiObject2
として返されます。Deployment の構成を
BySelector
は、複数のプロパティを連結してプロパティを絞り込むことができます。
できます。一致する UI 要素が見つからない場合は、null
が返されます。
hasChild()
または hasDescendant()
メソッドを使用して、メッセージをネストできます。
複数の BySelector
インスタンスを使用できます。たとえば、次のコードサンプルは、
テストで、最初の ListView
を見つけるための検索を指定する方法
text プロパティを持つ子 UI 要素があります。
Kotlin
val listView: UiObject2 = device.findObject( By.clazz("android.widget.ListView") .hasChild( By.text("Apps") ) )
Java
UiObject2 listView = device.findObject( By.clazz("android.widget.ListView") .hasChild( By.text("Apps") ) );
セレクタの条件としてオブジェクトの状態を指定する方法が適切な場合もあります。対象
たとえば、オンにしたすべての要素のリストを選択して、
チェックボックスをオフにし、引数を true に設定して checked()
メソッドを呼び出します。
アクションを実行する
テストで UiObject2
オブジェクトを取得したら、
UI コンポーネントでユーザー インタラクションを実行する UiObject2
クラス
そのオブジェクトで表されるデータです。次のようなアクションの指定が可能です。
click()
: UI 要素の表示境界の中心をクリックします。drag()
: このオブジェクトを任意の座標にドラッグします。setText()
: 編集可能なフィールドに 表示されます。逆に、clear()
メソッドは既存のテキストを消去します。 入力します。swipe()
: 指定した方向にスワイプします。scrollUntil()
: 指定された方向へスクロール操作を行います。Condition
またはEventCondition
の条件が満たされるまで。
UI Automator テスト フレームワークでは、Intent を送信するか、
Context を取得し、シェルコマンドを使用せずにアクティビティを
オブジェクトを getContext()
で設定します。
次のスニペットは、テストで Intent を使用して テスト対象アプリです。この方法は、テストのみに関心がある場合に有用です。 ランチャーについては関係ありません
Kotlin
fun setUp() { ... // Launch a simple calculator app val context = getInstrumentation().context val intent = context.packageManager.getLaunchIntentForPackage(CALC_PACKAGE).apply { addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK) } // Clear out any previous instances context.startActivity(intent) device.wait(Until.hasObject(By.pkg(CALC_PACKAGE).depth(0)), TIMEOUT) }
Java
public void setUp() { ... // Launch a simple calculator app Context context = getInstrumentation().getContext(); Intent intent = context.getPackageManager() .getLaunchIntentForPackage(CALC_PACKAGE); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); // Clear out any previous instances context.startActivity(intent); device.wait(Until.hasObject(By.pkg(CALC_PACKAGE).depth(0)), TIMEOUT); }
結果を検証する
InstrumentationTestCase は TestCase を拡張するため、 アプリの UI コンポーネントが返すことをテストする標準の JUnit Assert メソッド 示されます。
次のスニペットは、画面内の複数のボタンをテストで見つける方法を示しています。 クリックして順番にクリックして、正しい結果が 表示されます。
Kotlin
private const val CALC_PACKAGE = "com.myexample.calc" fun testTwoPlusThreeEqualsFive() { // Enter an equation: 2 + 3 = ? device.findObject(By.res(CALC_PACKAGE, "two")).click() device.findObject(By.res(CALC_PACKAGE, "plus")).click() device.findObject(By.res(CALC_PACKAGE, "three")).click() device.findObject(By.res(CALC_PACKAGE, "equals")).click() // Verify the result = 5 val result: UiObject2 = device.findObject(By.res(CALC_PACKAGE, "result")) assertEquals("5", result.text) }
Java
private static final String CALC_PACKAGE = "com.myexample.calc"; public void testTwoPlusThreeEqualsFive() { // Enter an equation: 2 + 3 = ? device.findObject(By.res(CALC_PACKAGE, "two")).click(); device.findObject(By.res(CALC_PACKAGE, "plus")).click(); device.findObject(By.res(CALC_PACKAGE, "three")).click(); device.findObject(By.res(CALC_PACKAGE, "equals")).click(); // Verify the result = 5 UiObject2 result = device.findObject(By.res(CALC_PACKAGE, "result")); assertEquals("5", result.getText()); }
デバイスまたはエミュレータで UI Automator テストを実行する
UI Automator テストは、Android Studio または
使用します。AndroidJUnitRunner
をデフォルトとして指定してください。
インストルメンテーションランナーを使用します
その他の例
システム UI を操作する
UI Automator は、システムを含め、画面上のあらゆる要素を操作できます。 追加することをおすすめします。次のコード スニペットをご覧ください。
Kotlin
// Opens the System Settings. device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) device.executeShellCommand("am start -a android.settings.SETTINGS")
Java
// Opens the System Settings. device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()); device.executeShellCommand("am start -a android.settings.SETTINGS");
Kotlin
// Opens the notification shade. device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) device.openNotification()
Java
// Opens the notification shade. device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()); device.openNotification();
Kotlin
// Opens the Quick Settings shade. device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) device.openQuickSettings()
Java
// Opens the Quick Settings shade. device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()); device.openQuickSettings();
Kotlin
// Get the system clock. device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) UiObject2 clock = device.findObject(By.res("com.android.systemui:id/clock")) print(clock.getText())
Java
// Get the system clock. device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()); UiObject2 clock = device.findObject(By.res("com.android.systemui:id/clock")); print(clock.getText());
遷移を待つ
画面の遷移には時間がかかる場合があり、その継続時間の予測は信頼できません。 オペレーションの実行後は UI Automator が待機する必要があります。UI Automator これには複数の方法があります。
UiDevice.performActionAndWait(Runnable action, EventCondition<U> condition, long timeout)
: たとえば、ボタンをクリックして新しいウィンドウが表示されるまで待機するには、device.performActionAndWait(() -> button.click(), Until.newWindow(), timeout)
を呼び出します。UiDevice.wait(Condition<Object, U> condition, long timeout)
: たとえば、デバイスに特定のUiObject2
があるまで待機するには、device.wait(device.hasObject(By.text("my_text")), timeout);
を呼び出します。UiObject2.wait(@NonNull Condition<Object, U> condition, long timeout)
: たとえば、チェックボックスがオンになるまで待機するには、checkbox.wait(Until.checked(true), timeout);
を呼び出します。UiObject2.clickAndWait(@NonNull EventCondition<U> condition, long timeout)
: たとえば、ボタンをクリックして新しいウィンドウが表示されるまで待機するには、button.clickAndWait(Until.newWindow(), timeout);
を呼び出します。UiObject2.scrollUntil(@NonNull Direction direction, @NonNull Condition<Object, U> condition)
: たとえば、新しいオブジェクトが表示されるまで下にスクロールするには、object.scrollUntil(Direction.DOWN, Until.hasObject(By.text('new_obj')));
を呼び出します。UiObject2.scrollUntil(@NonNull Direction direction, @NonNull EventCondition<U> condition)
: たとえば、一番下までスクロールするには、object.scrollUntil(Direction.DOWN, Until.scrollFinished(Direction.DOWN));
を呼び出します。
次のコード スニペットは、UI Automator を使用して [Do Not] をオフにする方法を示しています。
システム設定でサイレント モードを使用する(performActionAndWait()
メソッドを使用)
遷移を待機します。
Kotlin
@Test @SdkSuppress(minSdkVersion = 21) @Throws(Exception::class) fun turnOffDoNotDisturb() { device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) device.performActionAndWait({ try { device.executeShellCommand("am start -a android.settings.SETTINGS") } catch (e: IOException) { throw RuntimeException(e) } }, Until.newWindow(), 1000) // Check system settings has been opened. Assert.assertTrue(device.hasObject(By.pkg("com.android.settings"))) // Scroll the settings to the top and find Notifications button var scrollableObj: UiObject2 = device.findObject(By.scrollable(true)) scrollableObj.scrollUntil(Direction.UP, Until.scrollFinished(Direction.UP)) val notificationsButton = scrollableObj.findObject(By.text("Notifications")) // Click the Notifications button and wait until a new window is opened. device.performActionAndWait({ notificationsButton.click() }, Until.newWindow(), 1000) scrollableObj = device.findObject(By.scrollable(true)) // Scroll down until it finds a Do Not Disturb button. val doNotDisturb = scrollableObj.scrollUntil( Direction.DOWN, Until.findObject(By.textContains("Do Not Disturb")) ) device.performActionAndWait({ doNotDisturb.click() }, Until.newWindow(), 1000) // Turn off the Do Not Disturb. val turnOnDoNotDisturb = device.findObject(By.text("Turn on now")) turnOnDoNotDisturb?.click() Assert.assertTrue(device.wait(Until.hasObject(By.text("Turn off now")), 1000)) }
Java
@Test @SdkSuppress(minSdkVersion = 21) public void turnOffDoNotDisturb() throws Exception{ device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()); device.performActionAndWait(() -> { try { device.executeShellCommand("am start -a android.settings.SETTINGS"); } catch (IOException e) { throw new RuntimeException(e); } }, Until.newWindow(), 1000); // Check system settings has been opened. assertTrue(device.hasObject(By.pkg("com.android.settings"))); // Scroll the settings to the top and find Notifications button UiObject2 scrollableObj = device.findObject(By.scrollable(true)); scrollableObj.scrollUntil(Direction.UP, Until.scrollFinished(Direction.UP)); UiObject2 notificationsButton = scrollableObj.findObject(By.text("Notifications")); // Click the Notifications button and wait until a new window is opened. device.performActionAndWait(() -> notificationsButton.click(), Until.newWindow(), 1000); scrollableObj = device.findObject(By.scrollable(true)); // Scroll down until it finds a Do Not Disturb button. UiObject2 doNotDisturb = scrollableObj.scrollUntil(Direction.DOWN, Until.findObject(By.textContains("Do Not Disturb"))); device.performActionAndWait(()-> doNotDisturb.click(), Until.newWindow(), 1000); // Turn off the Do Not Disturb. UiObject2 turnOnDoNotDisturb = device.findObject(By.text("Turn on now")); if(turnOnDoNotDisturb != null) { turnOnDoNotDisturb.click(); } assertTrue(device.wait(Until.hasObject(By.text("Turn off now")), 1000)); }
参考情報
Android テストで UI Automator を使用する方法について詳しくは、 ご覧ください
リファレンス ドキュメント:
サンプル
- BasicSample: UI Automator の基本的なサンプルです。