Esistono tre modi principali per interagire con gli elementi dell'interfaccia utente:
- I finder consentono di selezionare uno o più elementi (o nodi nell'albero semantico) per eseguire asserzioni o 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 semantico.
Finder
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 sfogliare l'elenco completo nel
foglio illustrativo dei test di Compose.
Selezionare un singolo nodo
composeTestRule.onNode(<<SemanticsMatcher>>, useUnmergedTree = false): SemanticsNodeInteraction
// Example
composeTestRule
.onNode(hasText("Button")) // Equivalent to onNodeWithText("Button")
Selezionare 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 figli. 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 la corrispondenza di 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 le funzioni di convenienza per le asserzioni più comuni, come
assertExists, assertIsDisplayed e assertTextEquals.
Puoi sfogliare l'elenco completo nel foglio illustrativo dei test di Compose.
Esistono anche funzioni per controllare 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 sfogliare l'elenco completo nel foglio illustrativo dei test di Compose.
Matcher
Sono disponibili diversi matcher per testare il codice Compose.
Matcher gerarchici
I matcher gerarchici consentono di spostarsi verso l'alto o verso il basso 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 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 sfogliare l'elenco completo nel foglio illustrativo dei test di Compose.
Risorse aggiuntive
- Testare le app su Android: la pagina di destinazione principale dei test di Android fornisce una visione più ampia dei principi e delle tecniche di test.
- Principi di 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.
- Testare 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 interfacce utente basate su visualizzazioni, la conoscenza di Espresso può comunque essere utile per alcuni aspetti dei test di Compose .