Test delle API

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

  • I rilevatori consentono di selezionare uno o più elementi (o nodi nell'albero della semantica) per creare asserzioni o eseguire azioni su di essi.
  • Le asserzioni vengono utilizzate per verificare che gli elementi esistano o abbiano determinati attributi.
  • Le azioni aggiungono eventi utente simulati agli elementi, ad esempio clic o altri gesti.

Alcune di queste API accettano un elemento SemanticsMatcher per fare riferimento a uno o più nodi nell'albero della semantica.

Ricercatori

Puoi utilizzare onNode e onAllNodes per selezionare rispettivamente uno o più nodi, ma puoi anche utilizzare dei programmi di ricerca per le ricerche più comuni, ad esempio onNodeWithText e onNodeWithContentDescription. Puoi sfogliare l'elenco completo nella scheda di riferimento di Compose Testing.

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 rispettivi 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 restituisce 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 restituisce 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 programmi di ricerca. Ad esempio, qui viene usata come strumento di ricerca di onNodeWithText.

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

Dichiarazioni

Controlla le affermazioni chiamando assert() sul SemanticsNodeInteraction restituito da una 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 sfogliare l'elenco completo nella scheda di riferimento di Compose Testing.

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 sfogliare l'elenco completo nella scheda di riferimento di Compose Testing.

Partite

È disponibile un'ampia gamma di matcher per testare il codice di Compose.

Matcher gerarchici

I matcher gerarchici consentono di aumentare o diminuire la semantica ed eseguire corrispondenze.

fun hasParent(matcher: SemanticsMatcher): SemanticsMatcher
fun hasAnySibling(matcher: SemanticsMatcher): SemanticsMatcher
fun hasAnyAncestor(matcher: SemanticsMatcher): SemanticsMatcher
fun hasAnyDescendant(matcher: SemanticsMatcher):  SemanticsMatcher

Ecco alcuni esempi di questi matcher utilizzati:

composeTestRule.onNode(hasParent(hasText("Button")))
    .assertIsDisplayed()

Selettori

Un modo alternativo per creare i test consiste nell'utilizzare i selettori, che possono rendere più leggibili alcuni test.

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

Puoi sfogliare l'elenco completo nella scheda di riferimento di Compose Testing.

Risorse aggiuntive

  • App di test su Android: la pagina di destinazione principale per i test di Android offre una visione più ampia sulle tecniche e sui concetti fondamentali dei 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 in locale, sulla tua workstation.
  • Test strumentati: è buona norma eseguire anche test con strumentazione. ovvero test eseguiti direttamente sul dispositivo.
  • Integrazione continua: l'integrazione continua consente di integrare i test nella pipeline di deployment.
  • Prova dimensioni dello schermo diverse: dato che sono disponibili molti dispositivi per gli utenti, dovresti testare schermi di dimensioni diverse.
  • Espresso: sebbene destinato alle UI basate su View, la conoscenza di Espresso può comunque essere utile per alcuni aspetti dei test di Compose.