Korzystanie z interfejsu UI Automator Legacy API

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

Platforma testowa UI Automator to interfejs API oparty na instrumentacji, który współpracuje z AndroidJUnitRunner mechanizmem uruchamiania testów. Dobrze nadaje się do pisania automatycznych testów w stylu czarnej skrzynki, w których kod testowy nie zależy od wewnętrznych szczegółów implementacji aplikacji docelowej.

Główne funkcje platformy testowej UI Automator:

  • Interfejs API do pobierania informacji o stanie i wykonywania operacji na urządzeniu docelowym. Więcej informacji znajdziesz w artykule Dostęp do stanu urządzenia.
  • Interfejsy API, które obsługują testowanie interfejsu w różnych aplikacjach. Więcej informacji znajdziesz w artykule Interfejsy API UI Automator.

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 aplikacja docelowa, i wykonywanie na nim operacji. Możesz wywoływać jej metody, aby uzyskiwać dostęp do właściwości urządzenia, takich jak bieżąca orientacja czy rozmiar ekranu. Klasa UiDevice umożliwia też wykonywanie tych działań:

  1. Zmiana orientacji urządzenia.
  2. Naciskanie przycisków sprzętowych, np. „przycisk zwiększania głośności”.
  3. Naciskanie przycisków Wstecz, Strona główna lub Menu.
  4. Otwieranie obszaru powiadomień.
  5. Robienie zrzutu ekranu bieżącego okna.

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

Interfejsy API UI Automator

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

  • UiObject2: reprezentuje 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 ustawianie kluczowych parametrów do uruchamiania testów UI Automator.

Na przykład ten kod pokazuje, jak napisać scenariusz testowania, 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 Automator

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 z biblioteką UI Automator:

Kotlin

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

Dynamiczny

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

Aby zoptymalizować testowanie za pomocą UI Automator, najpierw sprawdź komponenty interfejsu aplikacji docelowej i upewnij się, że są one dostępne. Te wskazówki dotyczące optymalizacji znajdziesz w 2 kolejnych sekcjach.

Sprawdzanie interfejsu na urządzeniu

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

Narzędzie uiautomatorviewer udostępnia 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 Automator. 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 aplikację docelową na urządzeniu fizycznym.
  2. Podłącz urządzenie do komputera używanego do programowania.
  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 w panelu po lewej stronie, aby zobaczyć komponenty interfejsu zidentyfikowane przez narzędzie uiautomatorviewer. Właściwości są wymienione w prawym dolnym panelu, a hierarchia układu – w prawym górnym panelu.
  3. Opcjonalnie kliknij przycisk Przełącz węzły NAF , aby zobaczyć komponenty interfejsu, które są niedostępne dla UI Automator. W przypadku tych komponentów mogą być dostępne tylko ograniczone informacje.

Aby dowiedzieć się więcej o typowych typach komponentów interfejsu udostępnianych przez Androida, przeczytaj artykuł Interfejs użytkownika.

Sprawdzanie, czy aktywność jest dostępna

Platforma testowa UI Automator działa lepiej w przypadku aplikacji, które zaimplementowały funkcje ułatwień dostępu na Androida. Gdy 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 zrobiły.

Niektóre aplikacje używają jednak niestandardowych elementów interfejsu, aby zapewnić lepsze wrażenia użytkownika. Takie elementy nie będą automatycznie obsługiwać 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 konkretną klasę, która rozszerza ExploreByTouchHelper.
  2. Powiąż instancję nowej klasy z konkretnym niestandardowym elementem interfejsu, wywołując 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 Zwiększanie dostępności 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ą.

Na początku definicji klasy testowej dodaj adnotację @RunWith(AndroidJUnit4.class). Musisz też określić klasę AndroidJUnitRunner, która jest dostępna w AndroidX Test, jako domyślny mechanizm uruchamiania testów. Ten krok jest opisany bardziej szczegółowo 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 jako argument obiekt Instrumentation.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().UiObject2
  3. Zasymuluj konkretną interakcję użytkownika, która ma być wykonana na tym komponencie interfejsu, wywołując metodę UiObject2. Na przykład wywołaj 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 testować 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.

Te kroki są bardziej szczegółowo opisane 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 ekranu. 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 sprzętowych padu kierunkowego oraz naciskanie przycisków Strona główna i Menu.

Dobrym rozwiązaniem jest rozpoczęcie testu od ekranu głównego urządzenia. Na ekranie głównym (lub w innej wybranej lokalizacji początkowej na urządzeniu) możesz wywoływać metody udostępniane przez interfejs UI Automator API, aby wybierać konkretne elementy interfejsu i wchodzić z nimi w interakcję.

Ten fragment kodu pokazuje, jak test może uzyskać instancję UiDevice i zasymulować naciśnięcie przycisku Strona główna:

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 18 interfejsu API) 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żywać instancji UiObject2 utworzonych w innych częściach testowania aplikacji. Pamiętaj, że platforma testowa UI Automator przeszukuje bieżący ekran w poszukiwaniu dopasowania za każdym razem, gdy test używa instancji UiObject2, aby kliknąć element interfejsu lub wysłać zapytanie o właściwość.

Ten fragment kodu pokazuje, jak test może tworzyć instancje UiObject2, które reprezentują przycisk Anuluj i przycisk 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 o konkretne elementy w wyświetlanym interfejsie.

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

Możesz użyć metody hasChild() lub hasDescendant(), aby zagnieżdżać wiele instancji BySelector. Na przykład ten fragment kodu pokazuje jak test może określić wyszukiwanie, aby znaleźć pierwszy 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 true.

Wykonywanie działań

Gdy test uzyska obiekt UiObject2, możesz wywoływać metody w klasie UiObject2, aby wykonywać interakcje użytkownika na komponencie 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 edytowalnym polu po wyczyszczeniu jego zawartości. Z kolei metoda clear() czyści istniejący tekst w edytowalnym polu.
  • 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, że uzyskasz obiekt Context za pomocą getContext().

Ten fragment kodu pokazuje, jak test może użyć intencji do uruchomienia testowanej aplikacji. To podejście jest przydatne, gdy interesuje Cię tylko testowanie aplikacji 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

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

Ten fragment kodu pokazuje, jak test może znaleźć 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 w wierszu poleceń. Upewnij się, że w projekcie jako domyślny mechanizm uruchamiania instrumentacji został określony AndroidJUnitRunner.

Więcej przykładów

Korzystanie z interfejsu systemu

UI Automator może wchodzić w interakcję ze wszystkim na ekranie, w tym z elementami systemu spoza aplikacji, jak pokazują te 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());

Czekanie 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 do tego kilka metod:

Ten fragment kodu pokazuje, jak za pomocą UI Automator 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 Automator w testach na Androida znajdziesz w tych materiałach.

Dokumentacja źródłowa:

Przykłady