I test di composizione vengono sincronizzati per impostazione predefinita con la tua UI. Quando chiami un'asserzione o un'azione con ComposeTestRule
, il test viene sincronizzato in anticipo, in attesa che l'albero dell'interfaccia utente sia inattivo.
In genere, non devi intraprendere alcuna azione. Tuttavia, ci sono alcuni casi limite che devi conoscere.
Quando un test viene sincronizzato, l'app Compose viene avanzata nel tempo utilizzando un 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 si verificherà alcuna ricomposizione e l'interfaccia utente sembrerà 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 composizione e non al resto dell'app.
Disattivare la sincronizzazione automatica
Quando chiami un'asserzione o un'azione tramite ComposeTestRule
, ad esempio
assertExists()
, il test viene sincronizzato con la UI di Compose. In alcuni casi
potresti voler interrompere questa sincronizzazione e controllare l'orologio manualmente. Ad esempio, puoi controllare il tempo per scattare screenshot accurati di un'animazione in un punto in cui la UI è ancora occupata. Per disattivare la sincronizzazione automatica,
imposta la proprietà autoAdvance
in mainClock
su false
:
composeTestRule.mainClock.autoAdvance = false
In genere, dovrai avanzare manualmente l'ora. Puoi avanzare esattamente di un
fotogramma con advanceTimeByFrame()
o di una durata specifica con
advanceTimeBy()
:
composeTestRule.mainClock.advanceTimeByFrame()
composeTestRule.mainClock.advanceTimeBy(milliseconds)
Risorse inattive
Compose può sincronizzare i test e la UI in modo che ogni azione e asserzione venga eseguita in uno stato di inattività, attendendo o facendo avanzare l'orologio in base alle necessità. Tuttavia, alcune operazioni asincrone i cui risultati influiscono sullo stato della UI possono essere eseguite in background mentre il test non ne è a conoscenza.
Crea e registra queste risorse inattive nel test in modo che vengano prese in considerazione quando si decide se l'app in fase di test è occupata o inattiva. Non devi intervenire a meno che tu non debba registrare risorse inattive aggiuntive, ad esempio se esegui un job in background che non è sincronizzato con Espresso o Compose.
Questa API è molto simile a Idling Resources di Espresso per indicare se
il soggetto in fase di test è inattivo o occupato. Utilizza la regola di test Crea per registrare
l'implementazione di IdlingResource
.
composeTestRule.registerIdlingResource(idlingResource)
composeTestRule.unregisterIdlingResource(idlingResource)
Sincronizzazione manuale
In alcuni casi, devi sincronizzare la UI Compose con altre parti del test o dell'app che stai testando.
La funzione waitForIdle()
attende che Compose sia inattivo, 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 i passaggi di disegno e layout
in attesa.
Inoltre, puoi far avanzare l'orologio fino a quando non viene soddisfatta una determinata condizione con
advanceTimeUntil()
.
composeTestRule.mainClock.advanceTimeUntil(timeoutMs) { condition }
Tieni presente che la condizione specificata deve controllare lo stato che può essere interessato da questo orologio (funziona solo con lo stato di Compose).
Attendi le condizioni
Qualsiasi condizione che dipende da un lavoro esterno, come il caricamento dei dati o la misurazione o il disegno di Android (ovvero la misurazione o il disegno esterni a Compose), deve utilizzare un concetto più generale come waitUntil()
:
composeTestRule.waitUntil(timeoutMs) { condition }
Puoi anche utilizzare uno qualsiasi degli
helper 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 dei test Android offre una visione più ampia dei fondamenti e delle tecniche di test.
- Nozioni di base sui test: scopri di più sui concetti fondamentali alla base del test di un'app per Android.
- Test locali: puoi eseguire alcuni test localmente, sulla tua workstation.
- Test strumentati: è buona norma eseguire anche test strumentati. ovvero test eseguiti direttamente sul dispositivo.
- Integrazione continua: L'integrazione continua consente di integrare i test nella pipeline di deployment.
- Testa diverse dimensioni dello schermo: con tanti dispositivi a disposizione degli utenti, devi eseguire test per diverse dimensioni dello schermo.
- Espresso: sebbene sia destinato alle UI basate sulla visualizzazione, la conoscenza di Espresso può comunque essere utile per alcuni aspetti dei test di Compose.