Sincronizzare i test

I test di Compose sono sincronizzati per impostazione predefinita con la tua UI. Quando chiami un'affermazione o un'azione con ComposeTestRule, il test viene sincronizzato in anticipo, in attesa che l'albero dell'interfaccia utente sia inattivo.

In genere, non è richiesta alcuna azione da parte tua. Tuttavia, ci sono alcuni casi limite che dovresti conoscere.

Quando viene sincronizzato un test, l'app Compose esegue un'avanzata nel tempo utilizzando una orologio virtuale. Ciò significa che i test di composizione non vengono eseguiti in tempo reale, quindi possono essere superati il più rapidamente possibile.

Tuttavia, se non utilizzi i metodi che sincronizzano i test, non verrà eseguita alcuna ricompozione e l'interfaccia utente sembrerà essere in pausa.

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

Tieni presente che questo requisito si applica solo alle gerarchie di Compose e non al resto dell'app.

Disattivare la sincronizzazione automatica

Quando chiami un'asserzione o un'azione tramite ComposeTestRule, come assertExists(), il test è sincronizzato con l'UI di Compose. In alcuni casi è consigliabile interrompere la sincronizzazione e controllare l'orologio personalmente. Ad esempio, puoi controllare il tempo per acquisire screenshot accurati di un'animazione in un punto in cui l'interfaccia utente sarebbe ancora occupata. Per disattivare la sincronizzazione automatica: imposta la proprietà autoAdvance in mainClock su false:

composeTestRule.mainClock.autoAdvance = false

In genere, poi avanzi manualmente l'ora. Puoi avanzare di un solo elemento frame con advanceTimeByFrame() o di una durata specifica con advanceTimeBy():

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

Risorse inattive

Compose può sincronizzare i test e l'interfaccia utente in modo che ogni azione e asserzione venga eseguita in uno stato inattivo, in attesa o facendo avanzare l'orologio in base alle esigenze. Tuttavia, alcune operazioni asincrone i cui risultati influiscono sullo stato dell'interfaccia utente possono essere eseguite in background senza che il test ne sia a conoscenza.

Crea e registra queste risorse inattive nel test in modo che vengano prese in considerazione quando decidi se l'app in test è occupata o inattiva. Non è necessario intervenire a meno che non sia necessario registrare risorse inattive aggiuntive, ad esempio se esegui un job in background non sincronizzato con Espresso o Compose.

Questa API è molto simile alle Risorse inattive di Espresso per indicare se il soggetto sottoposto a test è inattivo o occupato. Utilizza la regola di test Composizione per registrare l'implementazione del IdlingResource.

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

Sincronizzazione manuale

In alcuni casi, dovrai sincronizzare l'UI di Compose con altre parti di il test o l'app che stai testando.

La funzione waitForIdle() attende che Compose sia inattiva, ma la funzione dipende dalla proprietà autoAdvance:

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.

Tieni presente che in entrambi i casi waitForIdle() attende anche le passate di disegno e layout in attesa.

Inoltre, è possibile far avanzare l'orologio fino a quando non viene soddisfatta una advanceTimeUntil()

composeTestRule.mainClock.advanceTimeUntil(timeoutMs) { condition }

Tieni presente che la condizione specificata deve controllare lo stato che può essere interessato da questo timer (funziona solo con lo stato Scrittura).

Attendi le condizioni

Qualsiasi condizione che dipende da un'operazione esterna, come il caricamento dei dati o le misurazioni o i disegni di Android (ovvero misurazioni o disegni esterni a Compose), deve utilizzare un concetto più generale come waitUntil():

composeTestRule.waitUntil(timeoutMs) { condition }

Puoi anche utilizzare uno qualsiasi dei Assistenti waitUntil:

composeTestRule.waitUntilAtLeastOneExists(matcher, timeoutMs)

composeTestRule.waitUntilDoesNotExist(matcher, timeoutMs)

composeTestRule.waitUntilExactlyOneExists(matcher, timeoutMs)

composeTestRule.waitUntilNodeCount(matcher, count, timeoutMs)

Risorse aggiuntive

  • Testare le app su Android: la pagina di destinazione principale per i test su Android offre una visione più ampia delle nozioni di base e delle tecniche di test.
  • Concetti fondamentali dei test: scopri di più sui concetti fondamentali alla base dei test di un'app per Android.
  • Test locali: puoi eseguire alcuni test localmente, sulla tua workstation.
  • Test strumentati: va bene di eseguire anche test strumentati. ovvero test eseguiti direttamente sul dispositivo.
  • Integrazione continua: L'integrazione continua ti consente di integrare i test nel tuo deployment una pipeline o un blocco note personalizzato.
  • Prova schermi di dimensioni diverse: con tra i tanti dispositivi disponibili per gli utenti, è consigliabile testare dimensioni.
  • Espresso: sebbene sia destinato alle UI basate su visualizzazioni, le conoscenze di Espresso possono essere utili per alcuni aspetti dei test di Compose.