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.
  • Aktionen fügen simulierte Nutzerereignisse in die Elemente ein, z. B. Klicks oder andere Gesten.

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

Sucher

Sie können onNode und onAllNodes verwenden, um einen oder mehrere Knoten auszuwählen. Sie können aber auch die Convenience-Finder für die häufigsten Suchen verwenden, z. B. onNodeWithText und onNodeWithContentDescription. Die vollständige Liste finden Sie auf der Übersicht zu Composer-Tests.

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

Baum nicht verbunden

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

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

In einem Test können Sie mit printToLog() den Semantikbaum anzeigen lassen:

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 nicht zusammengeführt abgleichen müssen, können Sie useUnmergedTree auf true setzen:

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 er beispielsweise in einem onNodeWithText-Finder verwendet.

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

Assertions

Prüfen Sie Assertions, indem Sie assert() für die SemanticsNodeInteraction aufrufen, die 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 Convenience-Funktionen für die gängigsten Assertions verwenden, z. B. assertExists, assertIsDisplayed und assertTextEquals. Die vollständige Liste finden Sie auf der Übersicht zu Composer-Tests.

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ügen:

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

Hier einige Beispiele für Aktionen:

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

Die vollständige Liste finden Sie auf der Übersicht zu Composer-Tests.

Matcher

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

Hierarchische Matcher

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 Abgleichkriterien:

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 können.

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

Die vollständige Liste finden Sie auf der Übersicht zu Composer-Tests.

Zusätzliche Ressourcen

  • Apps unter Android testen: Die Haupt-Landingpage für Android-Tests bietet einen umfassenderen Überblick über die Grundlagen und Testverfahren.
  • Testgrundlagen:Hier findest du weitere Informationen zu den Kernkonzepten, die dem Testen von Android-Apps zugrunde liegen.
  • Lokale Tests:Sie können einige Tests lokal auf Ihrer eigenen Workstation ausführen.
  • Instrumentierte Tests:Es empfiehlt sich, auch instrumentierte Tests auszuführen. Das sind Tests, die direkt auf dem Gerät ausgeführt werden.
  • Kontinuierliche Integration: Mit der kontinuierlichen Integration können Sie Ihre Tests in Ihre Bereitstellungspipeline einbinden.
  • Verschiedene Bildschirmgrößen testen:Da einige Geräte den Nutzern zur Verfügung stehen, solltest du verschiedene Bildschirmgrößen testen.
  • Espresso: Diese Funktion ist zwar für Ansichtsbasierte Benutzeroberflächen gedacht, kann aber bei einigen Aspekten des Compose-Tests hilfreich sein.