Tests synchronisieren

Erstellungstests werden standardmäßig mit Ihrer UI synchronisiert. Wenn Sie eine Assertion oder eine Aktion mit ComposeTestRule aufrufen, wird der Test vorher synchronisiert und gewartet, bis die UI-Struktur inaktiv ist.

Normalerweise müssen Sie nichts unternehmen. Es gibt jedoch einige Grenzfälle, die Sie kennen sollten.

Bei der Synchronisierung eines Tests wird die Erstellungs-App mithilfe einer virtuellen Uhr zeitlich verschoben. Das bedeutet, dass Compose-Tests nicht in Echtzeit ausgeführt werden und so schnell wie möglich bestanden werden können.

Wenn Sie die Methoden zum Synchronisieren Ihrer Tests jedoch nicht verwenden, erfolgt keine Neuzusammensetzung und die UI wird als pausiert angezeigt.

@Test
fun counterTest() {
    val myCounter = mutableStateOf(0) // State that can cause recompositions.
    var lastSeenValue = 0 // Used to track recompositions.
    composeTestRule.setContent {
        Text(myCounter.value.toString())
        lastSeenValue = myCounter.value
    }
    myCounter.value = 1 // The state changes, but there is no recomposition.

    // Fails because nothing triggered a recomposition.
    assertTrue(lastSeenValue == 1)

    // Passes because the assertion triggers recomposition.
    composeTestRule.onNodeWithText("1").assertExists()
}

Diese Anforderung gilt nur für Compose-Hierarchien und nicht für den Rest der Anwendung.

Automatische Synchronisierung deaktivieren

Wenn Sie eine Assertion oder Aktion über ComposeTestRule wie assertExists() aufrufen, wird der Test mit der Compose-UI synchronisiert. In einigen Fällen möchten Sie möglicherweise diese Synchronisierung stoppen und die Uhr selbst steuern. Sie können beispielsweise festlegen, wie lange es dauert, bis genaue Screenshots einer Animation an einer Stelle aufgenommen werden, an der die Benutzeroberfläche noch überlastet ist. Wenn Sie die automatische Synchronisierung deaktivieren möchten, setzen Sie das Attribut autoAdvance in mainClock auf false:

composeTestRule.mainClock.autoAdvance = false

In der Regel setzen Sie die Zeit dann selbst fort. Sie können mit advanceTimeByFrame() genau einen Frame oder mit advanceTimeBy() um eine bestimmte Dauer vorspringen:

composeTestRule.mainClock.advanceTimeByFrame()
composeTestRule.mainClock.advanceTimeBy(milliseconds)

Inaktive Ressourcen

Mit Compose können Tests und die UI synchronisiert werden, sodass jede Aktion und Assertion im Ruhezustand ausgeführt wird, entweder im Wartezustand oder im Bedarfsfall. Einige asynchrone Vorgänge, deren Ergebnisse sich auf den UI-Status auswirken, können jedoch im Hintergrund ausgeführt werden, wenn der Test sie nicht erkennt.

Erstellen und registrieren Sie diese inaktiven Ressourcen im Test, damit sie bei der Entscheidung, ob die zu testende Anwendung ausgelastet oder inaktiv ist, berücksichtigt werden. Sie müssen nur dann Maßnahmen ergreifen, wenn Sie zusätzliche inaktive Ressourcen registrieren müssen, z. B. wenn Sie einen Hintergrundjob ausführen, der nicht mit Espresso oder Composer synchronisiert wird.

Diese API ist den inaktiven Ressourcen von Espresso sehr ähnlich, um anzugeben, ob das zu testende Element inaktiv oder ausgelastet ist. Registriere die Implementierung von IdlingResource mit der Testregel „Compose“.

composeTestRule.registerIdlingResource(idlingResource)
composeTestRule.unregisterIdlingResource(idlingResource)

Manuelle Synchronisierung

In bestimmten Fällen müssen Sie die Compose-UI mit anderen Teilen des Tests oder der zu testenden Anwendung synchronisieren.

Die Funktion waitForIdle() wartet, bis Compose inaktiv ist. Die Funktion hängt jedoch vom Attribut autoAdvance ab:

composeTestRule.mainClock.autoAdvance = true // Default
composeTestRule.waitForIdle() // Advances the clock until Compose is idle.

composeTestRule.mainClock.autoAdvance = false
composeTestRule.waitForIdle() // Only waits for idling resources to become idle.

In beiden Fällen wartet waitForIdle() auch auf ausstehende Zeichen- und Layout-Durchläufe.

Außerdem können Sie die Uhr verschieben, bis eine bestimmte Bedingung mit advanceTimeUntil() erfüllt ist.

composeTestRule.mainClock.advanceTimeUntil(timeoutMs) { condition }

Die angegebene Bedingung sollte den Status prüfen, auf den sich diese Uhr auswirken kann. Sie funktioniert nur mit dem Status „Compose“.

Auf Bedingungen warten

Für jede Bedingung, die von externer Arbeit abhängt, z. B. das Laden von Daten oder das Messen oder Zeichnen von Android (d. h. Messen oder Zeichnen außerhalb von Compose) sollte ein allgemeineres Konzept wie waitUntil() verwendet werden:

composeTestRule.waitUntil(timeoutMs) { condition }

Sie können auch einen der waitUntil-Hilfsprogramme verwenden:

composeTestRule.waitUntilAtLeastOneExists(matcher, timeoutMs)

composeTestRule.waitUntilDoesNotExist(matcher, timeoutMs)

composeTestRule.waitUntilExactlyOneExists(matcher, timeoutMs)

composeTestRule.waitUntilNodeCount(matcher, count, timeoutMs)

Zusätzliche Ressourcen

  • Apps unter Android testen: Die Haupt-Landingpage für Android-Tests bietet einen umfassenderen Überblick über die Grundlagen und Testverfahren.
  • Testgrundlagen:Hier findest du weitere Informationen zu den Kernkonzepten, die dem Testen von Android-Apps zugrunde liegen.
  • Lokale Tests:Sie können einige Tests lokal auf Ihrer eigenen Workstation ausführen.
  • Instrumentierte Tests:Es empfiehlt sich, auch instrumentierte Tests auszuführen. Das sind Tests, die direkt auf dem Gerät ausgeführt werden.
  • Kontinuierliche Integration: Mit der kontinuierlichen Integration können Sie Ihre Tests in Ihre Bereitstellungspipeline einbinden.
  • Verschiedene Bildschirmgrößen testen:Da einige Geräte den Nutzern zur Verfügung stehen, solltest du verschiedene Bildschirmgrößen testen.
  • Espresso: Diese Funktion ist zwar für Ansichtsbasierte Benutzeroberflächen gedacht, kann aber bei einigen Aspekten des Compose-Tests hilfreich sein.