I test di composizione vengono sincronizzati per impostazione predefinita con l'interfaccia utente. 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 di cui dovresti essere a conoscenza.
Quando viene sincronizzato un test, l'app Compose esegue un'avanzamento temporale utilizzando un orologio virtuale. Ciò significa che i test di Compose non vengono eseguiti in tempo reale, quindi possono superarli 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 composizione e non al resto dell'app.
Disattivare la sincronizzazione automatica
Quando chiami un'affermazione o un'azione tramite ComposeTestRule
, ad esempio
assertExists()
, il test viene sincronizzato con l'interfaccia utente di Compose. In alcuni casi puoi decidere di 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 si avanza l'orario personalmente. Puoi avanzare di esattamente 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 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 l'oggetto in 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, devi sincronizzare l'interfaccia utente di Compose con altre parti del test o dell'app che stai testando.
La funzione waitForIdle()
attende che Scrittura sia inattiva, ma 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, 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 dovrebbe controllare lo stato che può essere interessato da questo orologio (funziona solo con lo stato di Compose).
Attendi 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 degli waitUntil
helper:
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 di Android offre una visione più ampia delle nozioni di base 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 con strumenti: è buona prassi eseguire anche test con strumenti. ovvero i test eseguiti direttamente sul dispositivo.
- Integrazione continua: l'integrazione continua ti consente di integrare i test nella pipeline di deployment.
- Esegui test su diverse dimensioni dello schermo: con così tanti dispositivi a disposizione degli utenti, devi testare diverse dimensioni dello schermo.
- Espresso: sebbene sia destinato alle UI basate su visualizzazioni, le conoscenze di Espresso possono essere utili per alcuni aspetti dei test di Compose.