Test delle API

Esistono tre modi principali per interagire con gli elementi dell'interfaccia utente:

  • I rilevatori ti consentono di selezionare uno o più elementi (o nodi nell'albero della semantica) per creare asserzioni o eseguire azioni su questi elementi.
  • Le asserzioni vengono utilizzate per verificare che gli elementi esistano o abbiano determinati attributi.
  • Le azioni inseriscono eventi utente simulati negli 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.

Cercatori

Puoi utilizzare onNode e onAllNodes per selezionare rispettivamente uno o più nodi, ma puoi anche utilizzare strumenti di ricerca di convenienza per le ricerche più comuni, ad esempio onNodeWithText e onNodeWithContentDescription. Puoi sfogliare l'elenco completo nella scheda di riferimento per il 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 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 della semantica:

composeTestRule.onRoot().printToLog("TAG")

Questo codice visualizza 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 visualizza 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 risultati di ricerca. Ad esempio, qui è utilizzato in un cercatore onNodeWithText.

composeTestRule
    .onNodeWithText("World", useUnmergedTree = true).assertIsDisplayed()

Asserzioni

Verifica le asserzioni chiamando assert() sul SemanticsNodeInteraction restituito da un strumento di ricerca 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 convenienza per le asserzioni più comuni, come assertExists, assertIsDisplayed e assertTextEquals. Puoi consultare l'elenco completo nella scheda di riferimento del test di Compose.

Esistono anche funzioni per verificare le asserzioni su un insieme 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, richiama una funzione perform…():

composeTestRule.onNode(...).performClick()

Di seguito sono riportati alcuni esempi di azioni:

performClick(),
performSemanticsAction(key),
performKeyPress(keyEvent),
performGesture { swipeLeft() }

Puoi sfogliare l'elenco completo nella scheda di riferimento per il test di Compose.

Corrispondenza

È disponibile una serie di matcher per testare il codice Compose.

Matcher gerarchici

I matcher gerarchici consentono di eseguire la corrispondenza in alto o in basso nell'albero della semantica.

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 selettori che possono rendere più leggibili alcuni test.

composeTestRule.onNode(hasTestTag("Players"))
    .onChildren()
    .filter(hasClickAction())
    .assertCountEquals(4)
    .onFirst()
    .assert(hasText("John"))

Puoi consultare l'elenco completo nella scheda di riferimento del test di Compose.

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.
  • Concetti fondamentali del 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. Vale a dire che i test vengono eseguiti direttamente sul dispositivo.
  • Integrazione continua: l'integrazione continua ti consente di integrare i test nella pipeline di deployment.
  • Prova schermi di dimensioni diverse: con alcuni dispositivi a disposizione degli utenti, ti conviene eseguire test per schermi di dimensioni diverse.
  • Espresso: sebbene sia destinata alle UI basate su View, le conoscenze di Espresso possono comunque essere utili per alcuni aspetti del test di Compose.