Esistono tre modi principali per interagire con gli elementi UI:
- I finder ti consentono di selezionare uno o più elementi (o nodi nell'albero semantico) per fare asserzioni o eseguire azioni su di essi.
- Le asserzioni vengono utilizzate per verificare che gli elementi esistano o abbiano determinati attributi.
- Le azioni inseriscono eventi utente simulati sugli elementi, come clic o altri gesti.
Alcune di queste API accettano un SemanticsMatcher per fare riferimento a uno o più nodi nell'albero della semantica.
Finders
Puoi utilizzare onNode e onAllNodes per selezionare rispettivamente uno o più nodi, ma puoi anche utilizzare i finder di convenienza per le ricerche più comuni, come onNodeWithText e onNodeWithContentDescription. Puoi consultare l'elenco completo nel
Cheat sheet per i test di Compose.
Seleziona un singolo nodo
composeTestRule.onNode(<<SemanticsMatcher>>, useUnmergedTree = false): SemanticsNodeInteraction
// Example
composeTestRule
.onNode(hasText("Button")) // Equivalent to onNodeWithText("Button")
Seleziona più nodi
composeTestRule
.onAllNodes(<<SemanticsMatcher>>): SemanticsNodeInteractionCollection
// Example
composeTestRule
.onAllNodes(hasText("Button")) // Equivalent to onAllNodesWithText("Button")
Albero non unito
Alcuni nodi uniscono le informazioni semantiche dei relativi nodi secondari. Ad esempio, un pulsante con due elementi di testo unisce le etichette degli elementi di testo:
MyButton {
Text("Hello")
Text("World")
}
Da un test, utilizza printToLog() per mostrare l'albero semantico:
composeTestRule.onRoot().printToLog("TAG")
Questo codice stampa il seguente output:
Node #1 at (...)px
|-Node #2 at (...)px
Role = 'Button'
Text = '[Hello, World]'
Actions = [OnClick, GetTextLayoutResult]
MergeDescendants = 'true'
Se devi trovare una corrispondenza con un nodo di quello che sarebbe l'albero non unito, puoi impostare useUnmergedTree su true:
composeTestRule.onRoot(useUnmergedTree = true).printToLog("TAG")
Questo codice stampa il seguente output:
Node #1 at (...)px
|-Node #2 at (...)px
OnClick = '...'
MergeDescendants = 'true'
|-Node #3 at (...)px
| Text = '[Hello]'
|-Node #5 at (83.0, 86.0, 191.0, 135.0)px
Text = '[World]'
Il parametro useUnmergedTree è disponibile in tutti i finder. Ad esempio, qui viene utilizzato in un finder onNodeWithText.
composeTestRule
.onNodeWithText("World", useUnmergedTree = true).assertIsDisplayed()
Asserzioni
Controlla le asserzioni chiamando assert() su SemanticsNodeInteraction
restituito da un finder con uno o più matcher:
// Single matcher:
composeTestRule
.onNode(matcher)
.assert(hasText("Button")) // hasText is a SemanticsMatcher
// Multiple matchers can use and / or
composeTestRule
.onNode(matcher).assert(hasText("Button") or hasText("Button2"))
Puoi anche utilizzare funzioni di utilità per le asserzioni più comuni, come assertExists, assertIsDisplayed e assertTextEquals.
Puoi consultare l'elenco completo nel foglio di riferimento per i test di Compose.
Esistono anche funzioni per verificare le asserzioni su una raccolta di nodi:
// Check number of matched nodes
composeTestRule
.onAllNodesWithContentDescription("Beatle").assertCountEquals(4)
// At least one matches
composeTestRule
.onAllNodesWithContentDescription("Beatle").assertAny(hasTestTag("Drummer"))
// All of them match
composeTestRule
.onAllNodesWithContentDescription("Beatle").assertAll(hasClickAction())
Azioni
Per inserire un'azione su un nodo, chiama una funzione perform…():
composeTestRule.onNode(...).performClick()
Ecco alcuni esempi di azioni:
performClick(),
performSemanticsAction(key),
performKeyPress(keyEvent),
performGesture { swipeLeft() }
Puoi consultare l'elenco completo nel Cheat sheet per i test di Compose.
Matcher
Sono disponibili vari matcher per testare il codice Compose.
Matcher gerarchici
I matcher gerarchici ti consentono di salire o scendere nell'albero semantico ed eseguire la corrispondenza.
fun hasParent(matcher: SemanticsMatcher): SemanticsMatcher
fun hasAnySibling(matcher: SemanticsMatcher): SemanticsMatcher
fun hasAnyAncestor(matcher: SemanticsMatcher): SemanticsMatcher
fun hasAnyDescendant(matcher: SemanticsMatcher): SemanticsMatcher
Ecco alcuni esempi di utilizzo di questi matcher:
composeTestRule.onNode(hasParent(hasText("Button")))
.assertIsDisplayed()
Selettori
Un modo alternativo per creare i test è utilizzare i selettori, che possono rendere alcuni test più leggibili.
composeTestRule.onNode(hasTestTag("Players"))
.onChildren()
.filter(hasClickAction())
.assertCountEquals(4)
.onFirst()
.assert(hasText("John"))
Puoi consultare l'elenco completo nel Cheat sheet per i test di Compose.
Risorse aggiuntive
- Testa le app su Android: la pagina di destinazione principale dei test su Android offre una visione più ampia dei concetti fondamentali e delle tecniche di test.
- Concetti fondamentali sul test di app Android: scopri di più sui concetti di base alla base del test di un'app per Android.
- Test locali: puoi eseguire alcuni test localmente, sulla tua workstation.
- Test di instrumentazione: è buona norma eseguire anche i test di instrumentazione. 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 così tanti dispositivi a disposizione degli utenti, devi eseguire test per diverse dimensioni dello schermo.
- Espresso: sebbene sia destinato alle UI basate su View, la conoscenza di Espresso può comunque essere utile per alcuni aspetti dei test di Compose.