Compose si integra con i framework di test comuni.
Interoperabilità con Espresso
In un'app ibrida, puoi trovare i componenti di Compose all'interno delle gerarchie di visualizzazione e
le visualizzazioni all'interno dei composable di Compose (tramite il composable AndroidView).
Non sono necessari passaggi speciali per la corrispondenza di entrambi i tipi. Abbina le visualizzazioni con
onView di Espresso e gli elementi Compose con ComposeTestRule.
@Test
fun androidViewInteropTest() {
// Check the initial state of a TextView that depends on a Compose state.
Espresso.onView(withText("Hello Views")).check(matches(isDisplayed()))
// Click on the Compose button that changes the state.
composeTestRule.onNodeWithText("Click here").performClick()
// Check the new value.
Espresso.onView(withText("Hello Compose")).check(matches(isDisplayed()))
}
Aggiungi la semantica con ambito di visualizzazione per i test di interoperabilità di Compose
Limitare le ricerche di Compose a visualizzazioni specifiche
Quando esegui la migrazione di UI complesse a Compose, potresti riscontrare elementi Compose identici nidificati all'interno di più View Android tradizionali, ad esempio all'interno di un RecyclerView o di un ViewPager. In questi scenari, una ricerca standard di Compose
come onNodeWithText("Save") potrebbe non riuscire e restituire l'errore "Trovati più nodi".
Anziché modificare il codice di produzione per inserire tag di test dinamici per distinguere questi elementi, puoi limitare l'ambito del test di Compose direttamente a una View Android specifica.
Utilizza l'API onRootWithViewInteraction nella regola di test. Questa funzione accetta
un ViewInteraction Espresso, consentendoti di sfruttare Espresso per isolare una
visualizzazione container specifica ed eseguire interazioni di composizione esclusivamente all'interno
di quella gerarchia con ambito.
Interagire con una voce di elenco
Se devi interagire con un elemento Compose all'interno di una riga RecyclerView
specifica, utilizza Espresso per individuare la riga, quindi limita l'interazione con Compose a questa riga.
Vengono ignorati gli elementi di composizione identici in tutte le altre righe.
@Test fun testComposeButtonInsideRecyclerViewItem() = runComposeUiTest { // Scroll to the desired position using Espresso Espresso.onView(withId(recyclerViewId)) .perform(RecyclerViewActions.scrollToPosition<MyViewHolder>(3)) // Define an Espresso ViewInteraction that uniquely identifies the row val rowView = Espresso.onView( allOf( withId(rootViewId), hasDescendant(withText("Item #3")) ) ) // Scope the Compose search strictly to that specific row View onRootWithViewInteraction(rowView) .onNode(hasText("Like")) .performClick() }
Risolvere l'ambiguità nei ViewPager
Quando in memoria sono presenti più frammenti con layout di composizione identici contemporaneamente, puoi limitare la ricerca all'ID View radice del frammento specifico per evitare ambiguità nella corrispondenza.
@Test fun testComposeButtonInsideViewPagerItem() = runComposeUiTest { // Swipe to the desired page using Espresso Espresso.onView(withId(viewPagerViewId)).perform(swipeLeft()) // Identify the specific container view using Espresso val fragmentB = Espresso.onView(withId(fragmentRootViewId)) // The generic text "Save" is now unique within this view scope onRootWithViewInteraction(fragmentB) .onNode(hasText("Save")) .assertIsDisplayed() }
Interoperabilità con UiAutomator
Per impostazione predefinita, i composable sono accessibili da UiAutomator solo tramite i loro
descrittori pratici (testo visualizzato, descrizione dei contenuti e così via). Se vuoi
accedere a qualsiasi componibile che utilizza Modifier.testTag, devi attivare
la proprietà semantica testTagsAsResourceId per il sottoalbero
del componibile specifico. L'attivazione di questo comportamento è utile per i composable che non hanno
altri handle unici, come i composable scorrevoli (ad esempio, LazyColumn).
Attiva la proprietà semantica una sola volta in alto nella gerarchia dei composable per
assicurarti che tutti i composable nidificati con Modifier.testTag siano accessibili da
UiAutomator.
Scaffold(
// Enables for all composables in the hierarchy.
modifier = Modifier.semantics {
testTagsAsResourceId = true
}
){
// Modifier.testTag is accessible from UiAutomator for composables nested here.
LazyColumn(
modifier = Modifier.testTag("myLazyColumn")
){
// Content
}
}
Qualsiasi elemento componibile con Modifier.testTag(tag) può essere accessibile con l'uso
di By.res(resourceName) utilizzando lo stesso tag di resourceName.
val device = UiDevice.getInstance(getInstrumentation())
val lazyColumn: UiObject2 = device.findObject(By.res("myLazyColumn"))
// Some interaction with the lazyColumn.
Risorse aggiuntive
- Testare le app su Android: la pagina di destinazione principale dei test Android offre una visione più ampia delle tecniche e delle nozioni di base sui 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 ti consente di integrare i test nella pipeline di deployment.
- Testa diverse dimensioni dello schermo: con molti 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.