Pisanie testów automatycznych za pomocą UI Automator (starsze wskazówki)

UI Automator to platforma do testowania interfejsu, która nadaje się do funkcjonalnego testowania interfejsu w różnych aplikacjach systemowych i zainstalowanych. Interfejsy UI Automator API umożliwiają interakcję z widocznymi elementami na urządzeniu niezależnie od tego, która Activity jest aktywna. Dzięki temu możesz wykonywać operacje takie jak otwieranie menu Ustawienia lub programu uruchamiającego aplikacje na urządzeniu testowym. Test może wyszukiwać komponent interfejsu za pomocą wygodnych deskryptorów, takich jak tekst wyświetlany w tym komponencie lub jego opis.

Platforma testowa UI Automator to interfejs API oparty na instrumentacji, który współpracuje z programem do uruchamiania testów AndroidJUnitRunner. Nadaje się do pisania automatycznych testów typu „czarna skrzynka”, w których kod testu nie zależy od wewnętrznych szczegółów implementacji testowanej aplikacji.

Główne funkcje platformy testowej UI Automator to:

Dostęp do stanu urządzenia

Platforma testowa UI Automator udostępnia klasę UiDevice, która umożliwia dostęp do urządzenia, na którym działa testowana aplikacja, i wykonywanie na nim operacji. Możesz wywoływać jego metody, aby uzyskać dostęp do właściwości urządzenia, takich jak bieżąca orientacja czy rozmiar wyświetlacza. Klasa UiDevice umożliwia też wykonywanie tych działań:

  1. Zmień orientację urządzenia.
  2. Naciśnij przyciski sprzętowe, np. „zwiększ głośność”.
  3. Naciśnij przycisk Wstecz, ekranu głównego lub menu.
  4. Otwórz obszar powiadomień.
  5. Zrób zrzut bieżącego okna.

Aby na przykład zasymulować naciśnięcie przycisku ekranu głównego, wywołaj metodę UiDevice.pressHome().

Interfejsy UI Automator API

Interfejsy API UI Automator umożliwiają pisanie niezawodnych testów bez konieczności poznawania szczegółów implementacji testowanej aplikacji. Za pomocą tych interfejsów API możesz przechwytywać komponenty interfejsu w różnych aplikacjach i nimi manipulować:

  • UiObject2: oznacza element interfejsu widoczny na urządzeniu.
  • BySelector: określa kryteria dopasowywania elementów interfejsu.
  • By: tworzy BySelector w zwięzły sposób.
  • Configurator: umożliwia ustawienie kluczowych parametrów do przeprowadzania testów UI Automator.

Na przykład poniższy kod pokazuje, jak napisać skrypt testowy, który otwiera aplikację Gmail na urządzeniu:

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);

Konfigurowanie UI Automatora

Zanim utworzysz test interfejsu za pomocą UI Automator, skonfiguruj lokalizację kodu źródłowego testu i zależności projektu zgodnie z opisem w artykule Konfigurowanie projektu na potrzeby AndroidX Test.

W pliku build.gradle modułu aplikacji na Androida musisz ustawić odwołanie do zależności do biblioteki UI Automator:

Kotlin

dependencies { ... androidTestImplementation("androidx.test.uiautomator:uiautomator:2.3.0") }

Groovy

dependencies { ... androidTestImplementation "androidx.test.uiautomator:uiautomator:2.3.0" }

Aby zoptymalizować testowanie za pomocą UI Automatora, najpierw sprawdź komponenty interfejsu aplikacji docelowej i upewnij się, że są dostępne. Wskazówki dotyczące optymalizacji opisujemy w 2 następnych sekcjach.

Sprawdzanie interfejsu na urządzeniu

Zanim zaprojektujesz test, sprawdź komponenty interfejsu widoczne na urządzeniu. Aby mieć pewność, że testy UI Automator mogą uzyskać dostęp do tych komponentów, sprawdź, czy mają one widoczne etykiety tekstowe, wartości android:contentDescription lub oba te elementy.

Narzędzie uiautomatorviewer zapewnia wygodny interfejs wizualny do sprawdzania hierarchii układu i wyświetlania właściwości komponentów interfejsu widocznych na pierwszym planie urządzenia. Te informacje umożliwiają tworzenie bardziej szczegółowych testów za pomocą UI Automatora. Możesz na przykład utworzyć selektor interfejsu, który pasuje do określonej widocznej właściwości.

Aby uruchomić narzędzie uiautomatorviewer:

  1. Uruchom docelową aplikację na urządzeniu fizycznym.
  2. Podłącz urządzenie do komputera deweloperskiego.
  3. Otwórz okno terminala i przejdź do katalogu <android-sdk>/tools/.
  4. Uruchom narzędzie za pomocą tego polecenia:
 $ uiautomatorviewer

Aby wyświetlić właściwości interfejsu aplikacji:

  1. W interfejsie uiautomatorviewer kliknij przycisk Zrzut ekranu urządzenia.
  2. Najedź kursorem na zrzut ekranu w panelu po lewej stronie, aby zobaczyć komponenty interfejsu zidentyfikowane przez narzędzie uiautomatorviewer. Właściwości są wymienione w panelu po prawej stronie u dołu, a hierarchia układu – w panelu po prawej stronie u góry.
  3. Opcjonalnie kliknij przycisk Toggle NAF Nodes (Przełącz węzły NAF), aby wyświetlić komponenty interfejsu, które są niedostępne dla UI Automatora. W przypadku tych komponentów może być dostępnych tylko ograniczona liczba informacji.

Więcej informacji o najpopularniejszych typach komponentów interfejsu udostępnianych przez Androida znajdziesz w artykule Interfejs użytkownika.

Sprawdź, czy aktywność jest dostępna

Platforma testowa UI Automator lepiej sprawdza się w przypadku aplikacji, w których zaimplementowano funkcje ułatwień dostępu na Androidzie. Jeśli używasz elementów interfejsu typu View lub podklasy View z pakietu SDK, nie musisz implementować obsługi ułatwień dostępu, ponieważ te klasy już to robią.

Niektóre aplikacje używają jednak niestandardowych elementów interfejsu, aby zapewnić użytkownikom większą wygodę. Takie elementy nie będą automatycznie obsługiwać funkcji ułatwień dostępu. Jeśli Twoja aplikacja zawiera instancje podklasy View, która nie pochodzi z pakietu SDK, dodaj do tych elementów funkcje ułatwień dostępu, wykonując te czynności:

  1. Utwórz klasę konkretną, która rozszerza klasę ExploreByTouchHelper.
  2. Powiąż instancję nowej klasy z określonym niestandardowym elementem interfejsu, wywołując metodę setAccessibilityDelegate().

Dodatkowe wskazówki dotyczące dodawania funkcji ułatwień dostępu do niestandardowych elementów widoku znajdziesz w artykule Tworzenie niestandardowych widoków z ułatwieniami dostępu. Więcej informacji o ogólnych sprawdzonych metodach dotyczących ułatwień dostępu na Androidzie znajdziesz w artykule Ułatwianie dostępu do aplikacji.

Tworzenie klasy testowej UI Automator

Klasa testowa UI Automator powinna być napisana w taki sam sposób jak klasa testowa JUnit 4. Więcej informacji o tworzeniu klas testowych JUnit 4 oraz używaniu asercji i adnotacji JUnit 4 znajdziesz w artykule Tworzenie klasy testu jednostkowego z instrumentacją.

Dodaj adnotację @RunWith(AndroidJUnit4.class) na początku definicji klasy testowej. Musisz też określić klasę AndroidJUnitRunner, która jest dostępna w AndroidX Test, jako domyślny mechanizm uruchamiania testów. Ten krok został szczegółowo opisany w artykule Uruchamianie testów UI Automator na urządzeniu lub emulatorze.

W klasie testowej UI Automator zaimplementuj ten model programowania:

  1. Aby uzyskać dostęp do urządzenia, które chcesz przetestować, wywołaj metodę getInstance() i przekaż jej obiekt Instrumentation jako argument.UiDevice
  2. Aby uzyskać dostęp do komponentu interfejsu wyświetlanego na urządzeniu (np. bieżącego widoku na pierwszym planie), wywołaj metodę findObject(). Zwróci ona obiekt UiObject2.
  3. Symuluj konkretną interakcję użytkownika z tym komponentem interfejsu, wywołując metodę UiObject2, np. scrollUntil(), aby przewijać, i setText(), aby edytować pole tekstowe. W razie potrzeby możesz wielokrotnie wywoływać interfejsy API w krokach 2 i 3, aby przetestować bardziej złożone interakcje użytkownika, które obejmują wiele komponentów interfejsu lub sekwencji działań użytkownika.
  4. Sprawdź, czy interfejs odzwierciedla oczekiwany stan lub zachowanie po wykonaniu tych interakcji użytkownika.

Szczegółowe informacje o tych krokach znajdziesz w sekcjach poniżej.

Dostęp do komponentów interfejsu

Obiekt UiDevice to podstawowy sposób uzyskiwania dostępu do stanu urządzenia i manipulowania nim. W testach możesz wywoływać metody UiDevice, aby sprawdzać stan różnych właściwości, takich jak bieżąca orientacja czy rozmiar wyświetlacza. Test może używać obiektu UiDevice do wykonywania działań na poziomie urządzenia, takich jak wymuszanie określonej orientacji urządzenia, naciskanie przycisków na padzie kierunkowym oraz naciskanie przycisków Home i Menu.

Warto rozpocząć test od ekranu głównego urządzenia. Na ekranie głównym (lub w innym miejscu początkowym wybranym na urządzeniu) możesz wywoływać metody udostępniane przez interfejs UI Automator API, aby wybierać określone elementy interfejsu i wchodzić z nimi w interakcję.

Poniższy fragment kodu pokazuje, jak test może uzyskać instancję UiDevice i zasymulować naciśnięcie przycisku Początek:

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);
    }
}

W tym przykładzie instrukcja @SdkSuppress(minSdkVersion = 18) pomaga zapewnić, że testy będą uruchamiane tylko na urządzeniach z Androidem 4.3 (poziom API 18) lub nowszym, zgodnie z wymaganiami platformy UI Automator.

Użyj metody findObject(), aby pobrać UiObject2, który reprezentuje widok pasujący do podanych kryteriów selektora. W razie potrzeby możesz ponownie użyć UiObject2instancji utworzonych w innych częściach testowania aplikacji. Pamiętaj, że platforma testowa UI Automator za każdym razem, gdy test używa instancji UiObject2 do kliknięcia elementu interfejsu lub wysłania zapytania o właściwość, przeszukuje bieżący wyświetlacz w poszukiwaniu dopasowania.

Poniższy fragment kodu pokazuje, jak test może tworzyć instancje UiObject2 reprezentujące przycisk Anuluj i OK w aplikacji.

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();
}

Określanie selektora

Jeśli chcesz uzyskać dostęp do konkretnego komponentu interfejsu w aplikacji, użyj klasy By, aby utworzyć instancję BySelector. BySelector reprezentuje zapytanie dotyczące konkretnych elementów wyświetlanego interfejsu.

Jeśli zostanie znalezionych więcej niż 1 pasujący element, jako element docelowy UiObject2 zostanie zwrócony pierwszy pasujący element w hierarchii układu. Podczas tworzenia BySelector możesz połączyć ze sobą kilka właściwości, aby zawęzić wyszukiwanie. Jeśli nie zostanie znaleziony żaden pasujący element interfejsu, zwracany jest znak null.

Aby zagnieździć wiele instancji BySelector, możesz użyć metody hasChild() lub hasDescendant(). Na przykład poniższy kod pokazuje, jak test może określić wyszukiwanie pierwszego elementu ListView, który ma podrzędny element interfejsu z właściwością tekstową.

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")
        )
);

W kryteriach selektora warto określić stan obiektu. Jeśli na przykład chcesz wybrać listę wszystkich zaznaczonych elementów, aby je wyczyścić, wywołaj metodę checked() z argumentem ustawionym na wartość „true”.

Wykonywanie działań

Gdy test uzyska obiekt UiObject2, możesz wywołać metody w klasie UiObject2, aby przeprowadzić interakcje użytkownika z komponentem interfejsu reprezentowanym przez ten obiekt. Możesz określić takie działania jak:

  • click() : klika środek widocznych granic elementu interfejsu.
  • drag() : przeciąga ten obiekt do dowolnych współrzędnych.
  • setText() : ustawia tekst w polu z możliwością edytowania po wyczyszczeniu zawartości pola. Z kolei metoda clear() usuwa istniejący tekst z pola z możliwością edycji.
  • swipe() : wykonuje działanie przesuwania w określonym kierunku.
  • scrollUntil(): wykonuje działanie przewijania w określonym kierunku, dopóki nie zostanie spełniony warunek Condition lub EventCondition.

Platforma testowa UI Automator umożliwia wysyłanie intencji lub uruchamianie aktywności bez używania poleceń powłoki. Wystarczy uzyskać obiekt Context za pomocą metody getContext().

Poniższy fragment kodu pokazuje, jak test może używać intencji do uruchamiania testowanej aplikacji. Ta metoda jest przydatna, gdy chcesz tylko przetestować aplikację kalkulatora i nie zależy Ci na programie uruchamiającym.

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);
}

Weryfikowanie wyników

Klasa InstrumentationTestCase rozszerza klasę TestCase, więc możesz używać standardowych metod Assert JUnit do testowania, czy komponenty interfejsu w aplikacji zwracają oczekiwane wyniki.

Poniższy fragment pokazuje, jak test może zlokalizować kilka przycisków w aplikacji kalkulatora, kliknąć je w odpowiedniej kolejności, a następnie sprawdzić, czy wyświetla się prawidłowy wynik.

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());
}

Uruchamianie testów UI Automator na urządzeniu lub emulatorze

Testy UI Automator możesz uruchamiać w Android Studio lub z poziomu wiersza poleceń. Upewnij się, że w projekcie jako domyślny program uruchamiający testy integracyjne podano AndroidJUnitRunner.

Więcej przykładów

Korzystanie z interfejsu systemu

UI Automator może wchodzić w interakcje ze wszystkimi elementami na ekranie, w tym z elementami systemowymi spoza aplikacji, jak pokazują poniższe fragmenty kodu:

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());

Czekaj na przejścia

Wyłącz zakłócanie
Rysunek 1. UI Automator wyłącza tryb Nie przeszkadzać na urządzeniu testowym.

Przejścia między ekranami mogą trwać długo, a przewidywanie ich czasu trwania jest zawodne, dlatego po wykonaniu operacji należy poczekać na UI Automator. UI Automator udostępnia kilka metod:

Poniższy fragment kodu pokazuje, jak za pomocą UI Automatora wyłączyć tryb Nie przeszkadzać w ustawieniach systemu za pomocą metody performActionAndWait(), która czeka na przejścia:

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));
}

Dodatkowe materiały

Więcej informacji o używaniu UI Automatora w testach na Androida znajdziesz w tych materiałach:

Dokumentacja:

Próbki