APIs testen

Es gibt drei Hauptmethoden für die Interaktion mit UI-Elementen:

  • Mit Suchern können Sie ein oder mehrere Elemente (oder Knoten im semantischen Baum) auswählen, um Behauptungen aufzustellen oder Aktionen darauf auszuführen.
  • Mit Behauptungen wird überprü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 sich auf einen oder mehrere Knoten im semantischen Baum zu beziehen.

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. Eine vollständige Liste finden Sie in der Kurzübersicht zum Erstellen von 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")

Nicht zusammengeführter Baum

Einige Knoten führen die Semantikinformationen ihrer untergeordneten Knoten zusammen. Bei einer Schaltfläche mit zwei Textelementen werden beispielsweise die Labels der Textelemente zusammengeführt:

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

Verwenden Sie in einem Test die Tastenkombination printToLog(), um den semantischen Baum aufzurufen:

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 nicht zusammengeführten Baums abgleichen möchten, können Sie useUnmergedTree auf true festlegen:

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

Dieser Code gibt 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 Suchern verfügbar. Hier wird er beispielsweise in einem onNodeWithText-Finder verwendet.

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

Behauptungen

Prüfen Sie Behauptungen, indem Sie assert() auf die SemanticsNodeInteraction anwenden, die von einem Finder mit einem oder mehreren Matchern zurückgegeben wird:

// 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 häufigsten Behauptungen verwenden, z. B. assertExists, assertIsDisplayed und assertTextEquals. Die vollständige Liste finden Sie in der Kurzübersicht für Compose-Tests.

Es gibt auch Funktionen, mit denen Behauptungen für eine Sammlung von Knoten geprüft werden können:

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

Wenn Sie eine Aktion in einen Knoten einfügen möchten, rufen Sie eine perform…()-Funktion auf:

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

Hier einige Beispiele für Aktionen:

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

Die vollständige Liste finden Sie in der Kurzübersicht zum Erstellen von Tests.

Übereinstimmungen

Für den Test Ihres Compose-Codes stehen verschiedene Übereinstimmungsmechanismen zur Verfügung.

Hierarchische Übereinstimmungen

Mit hierarchischen Abgleichern können Sie im semantischen Baum 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 einige Beispiele für die Verwendung dieser Abgleichsmechanismen:

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

Selektoren

Alternativ können Sie Auswahlen verwenden, um einige Tests übersichtlicher zu gestalten.

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

Die vollständige Liste finden Sie in der Kurzübersicht für Compose-Tests.

Zusätzliche Ressourcen

  • Apps unter Android testen: Die Haupt-Landingpage für Android-Tests bietet einen umfassenderen Überblick über die Grundlagen und Techniken des Testens.
  • Grundlagen des Testens: Hier erfahren Sie mehr über die grundlegenden Konzepte beim Testen einer Android-App.
  • Lokale Tests: Einige Tests können Sie 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.
  • Continuous Integration: Mit Continuous Integration können Sie Ihre Tests in Ihre Bereitstellungspipeline einbinden.
  • Unterschiedliche Bildschirmgrößen testen: Da Nutzern eine Vielzahl von Geräten zur Verfügung steht, sollten Sie verschiedene Bildschirmgrößen testen.
  • Espresso: Obwohl Espresso für viewbasierte UIs gedacht ist, können Kenntnisse zu Espresso auch für einige Aspekte von Compose-Tests hilfreich sein.