APIs testen

Es gibt drei Möglichkeiten, mit UI-Elementen zu interagieren:

  • Mit Findern können Sie ein oder mehrere Elemente (oder Knoten in der Semantikstruktur) auswählen, um Assertions zu erstellen oder Aktionen für sie auszuführen.
  • Mit Assertions wird geprüft, ob die Elemente vorhanden sind oder bestimmte Attribute haben.
  • Mit Aktionen werden simulierte Nutzerereignisse für die Elemente eingefügt, z. B. Klicks oder andere Gesten.

Einige dieser APIs akzeptieren ein SemanticsMatcher, um auf einen oder mehrere Knoten in der Semantikstruktur zu verweisen.

Finder

Sie können onNode und onAllNodes verwenden, um einen oder mehrere Knoten auszuwählen, aber Sie können auch praktische Finder für die häufigsten Suchanfragen verwenden, z. B. onNodeWithText und onNodeWithContentDescription. Die vollständige Liste finden Sie in der Spickzettel "Compose Testing".

Einzelnen Knoten auswählen

composeTestRule.onNode(<<SemanticsMatcher>>, useUnmergedTree = false): SemanticsNodeInteraction
// Example
composeTestRule
    .onNode(hasText("Button")) // Equivalent to onNodeWithText("Button")

Mehrere Knoten auswählen

composeTestRule
    .onAllNodes(<<SemanticsMatcher>>): SemanticsNodeInteractionCollection
// Example
composeTestRule
    .onAllNodes(hasText("Button")) // Equivalent to onAllNodesWithText("Button")

Nicht zusammengeführter Baum

Einige Knoten führen die Semantikinformationen ihrer untergeordneten Elemente zusammen. Eine Schaltfläche mit zwei Textelementen führt beispielsweise die Labels der Textelemente zusammen:

MyButton {
    Text("Hello")
    Text("World")
}

Verwenden Sie in einem Test printToLog(), um den Semantikbaum anzuzeigen:

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

Dieser Code gibt die folgende Ausgabe aus:

Node #1 at (...)px
 |-Node #2 at (...)px
   Role = 'Button'
   Text = '[Hello, World]'
   Actions = [OnClick, GetTextLayoutResult]
   MergeDescendants = 'true'

Wenn Sie einen Knoten des Baums unmerged zuordnen möchten, können Sie useUnmergedTree auf true festlegen:

composeTestRule.onRoot(useUnmergedTree = true).printToLog("TAG")

Dieser Code gibt die folgende Ausgabe aus:

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]'

Der Parameter useUnmergedTree ist in allen Findern verfügbar. Hier wird es beispielsweise in einer onNodeWithText-Suche verwendet.

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

Assertions

Prüfen Sie Assertions, indem Sie assert() im SemanticsNodeInteraction aufrufen, das von einem Finder mit einem oder mehreren Matchern zurückgegeben wurde:

// 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"))

Sie können auch praktische Funktionen für die gängigsten Assertions verwenden, z. B. assertExists, assertIsDisplayed und assertTextEquals. Eine vollständige Liste finden Sie in der Spickzettel "Compose Testing".

Es gibt auch Funktionen zum Prüfen von Assertions für eine Sammlung von Knoten:

// 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())

Aktionen

Rufen Sie eine perform…()-Funktion auf, um eine Aktion auf einem Knoten einzuführen:

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

Hier sind einige Beispiele für Aktionen:

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

Die vollständige Liste finden Sie in der Spickzettel "Compose Testing".

Matcher

Zum Testen des Compose-Codes stehen verschiedene Matcher zur Verfügung.

Hierarchische Abgleicher

Mit hierarchischen Matchern können Sie im Semantikbaum nach oben oder unten gehen und einen Abgleich durchführen.

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

Hier sind einige Beispiele für die Verwendung dieser Abgleichausdrücke:

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

Selektoren

Eine alternative Möglichkeit zum Erstellen von Tests ist die Verwendung von Selektoren, die einige Tests lesbarer machen.

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

Eine vollständige Liste finden Sie in der Spickzettel "Compose Testing".

Weitere Ressourcen

  • Test-Apps unter Android: Die Haupt-Landingpage für Android-Tests bietet einen umfassenderen Überblick über die Grundlagen und Techniken von Tests.
  • Grundlagen des Testens:Weitere Informationen zu den Kernkonzepten des Testens einer Android-App.
  • Lokale Tests:Sie können einige Tests lokal auf Ihrer eigenen Workstation ausführen.
  • Instrumentierte Tests:Es empfiehlt sich, auch instrumentierte Tests durchzuführen. Das sind Tests, die direkt auf dem Gerät ausgeführt werden.
  • Continuous Integration: Mit Continuous Integration können Sie Ihre Tests in Ihre Bereitstellungspipeline einbinden.
  • Testen Sie verschiedene Bildschirmgrößen:Da Nutzer auf vielen Geräten zur Verfügung stehen, sollten Sie Tests für unterschiedliche Bildschirmgrößen durchführen.
  • Espresso: Diese Espresso-Kenntnisse sind zwar für ansichtsbasierte UIs vorgesehen, können aber für einige Aspekte von Compose-Tests hilfreich sein.