Tests synchronisieren

Erstellungstests werden standardmäßig mit Ihrer UI synchronisiert. Wenn Sie eine Assertion oder Aktion mit dem ComposeTestRule, wird der Test synchronisiert und warten Sie, bis die Struktur der Benutzeroberfläche inaktiv ist.

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

Wenn ein Test synchronisiert wird, wird die Schreib-App mithilfe eines virtuelle Uhr. Das bedeutet, dass Compose-Tests nicht in Echtzeit ausgeführt werden und daher bestanden werden können. so schnell wie möglich zu machen.

Wenn Sie jedoch keine Methoden verwenden, die Ihre Tests synchronisieren, erfolgt keine Neuzusammensetzung und die Benutzeroberfläche wird als angehalten 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 App.

Automatische Synchronisierung deaktivieren

Wenn du über ComposeTestRule eine Assertion oder Aktion aufrufst, z. B. assertExists(), wird der Test mit der Compose-UI synchronisiert. In einigen Fällen können Sie diese Synchronisierung stoppen und die Uhr selbst steuern. So können Sie beispielsweise die Zeit steuern, um genaue Screenshots einer Animation zu einem Zeitpunkt aufzunehmen, an dem die Benutzeroberfläche noch aktiv ist. So deaktivieren Sie die automatische Synchronisierung: Legen Sie das Attribut autoAdvance in mainClock auf false fest:

composeTestRule.mainClock.autoAdvance = false

In der Regel setzen Sie die Zeit dann selbst fort. Mit advanceTimeByFrame() kannst du genau einen Frame vor- und mit advanceTimeBy() um eine bestimmte Dauer vorspulen:

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

Inaktive Ressourcen

Compose kann Tests und die Benutzeroberfläche so synchronisieren, dass jede Aktion und Behauptung im Inaktivitätsstatus ausgeführt wird, wobei die Uhr nach Bedarf angehalten oder vorangestellt wird. Einige asynchrone Vorgänge, deren Ergebnisse sich auf den UI-Status auswirken, können jedoch im Hintergrund ausgeführt werden, ohne dass sie im Test berücksichtigt werden.

Erstellen und registrieren Sie diese Inaktivitätsressourcen in Ihrem Test, damit sie bei der Entscheidung berücksichtigt werden, ob die getestete App aktiv oder inaktiv ist. Das solltest du nicht tun wenn Sie keine zusätzlichen inaktiven Ressourcen registrieren müssen, wenn Sie einen Hintergrundjob ausführen, der nicht mit Espresso oder Schreiben.

Diese API ist den inaktiven Ressourcen von Espresso sehr ähnlich, um anzugeben, ob dass das zu testende Subjekt inaktiv oder beschäftigt ist. Registrieren Sie sich mit der Testregel „Compose“ Die Implementierung von IdlingResource.

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

Manuelle Synchronisierung

In einigen Fällen müssen Sie die Compose-UI mit anderen Teilen des oder die App, die Sie testen.

Die Funktion waitForIdle() wartet, bis das Tool „Compose“ inaktiv ist, hängt aber von der Eigenschaft 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.

Beachten Sie, dass in beiden Fällen auch auf ausstehende Draw- und Layout-Passes gewartet wird.

Mit advanceTimeUntil() können Sie die Zeit auch vorspulen, bis eine bestimmte Bedingung erfüllt ist.

composeTestRule.mainClock.advanceTimeUntil(timeoutMs) { condition }

Die angegebene Bedingung sollte den Status prüfen, der von dieser Uhr beeinflusst werden kann. Sie funktioniert nur mit dem Status „Compose“ (Komponieren).

Auf Bedingungen warten

Für alle Bedingungen, die von externen Vorgängen abhängen, z. B. das Laden von Daten oder das Messen oder Zeichnen von Android (d. h. außerhalb von Compose), sollte ein allgemeineres Konzept wie waitUntil() verwendet werden:

composeTestRule.waitUntil(timeoutMs) { condition }

Sie können auch einen der waitUntil-Hilfsfunktionen 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 Techniken des Testens.
  • Testgrundlagen:Weitere Informationen Kernkonzepte beim Testen einer Android-App.
  • Lokale Tests: Einige Tests können Sie 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.
  • Continuous Integration: Mit Continuous Integration können Sie Ihre Tests in Ihre Bereitstellungspipeline einbinden.
  • Verschiedene Bildschirmgrößen testen:Mit Geräten verfügbar sind, sollten Sie auf verschiedenen Bildschirmen testen, Größen.
  • Espresso: Nur für Aufrufe Benutzeroberflächen und Espresso-Kenntnisse können bei einigen Aspekten von „Compose“ hilfreich sein Tests durchführen.