Es gibt drei Hauptmethoden für die Interaktion mit UI-Elementen:
- Mit Suchfunktionen können Sie ein oder mehrere Elemente (oder Knoten im Semantikbaum) 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 wie Klicks oder andere Gesten in die Elemente eingefügt.
Einige dieser APIs akzeptieren eine SemanticsMatcher, um auf einen oder mehrere Knoten im Semantikbaum zu verweisen.
Finder
Mit onNode und onAllNodes können Sie einen oder mehrere Knoten auswählen. Sie können aber auch praktische Suchfunktionen für die gängigsten Suchanfragen verwenden, z. B. onNodeWithText und onNodeWithContentDescription. Die vollständige Liste findest du im Spickzettel zum Testen von Compose.
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. Beispiel: Bei einer Schaltfläche mit zwei Textelementen werden die Labels der Textelemente zusammengeführt:
MyButton {
Text("Hello")
Text("World")
}
Verwenden Sie in einem Test printToLog(), um den Semantikbaum anzuzeigen:
composeTestRule.onRoot().printToLog("TAG")
Dieser Code gibt Folgendes 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üssen, können Sie useUnmergedTree auf true setzen:
composeTestRule.onRoot(useUnmergedTree = true).printToLog("TAG")
Dieser Code gibt Folgendes 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 Suchfunktionen verfügbar. Hier wird es beispielsweise in einem onNodeWithText-Finder verwendet.
composeTestRule
.onNodeWithText("World", useUnmergedTree = true).assertIsDisplayed()
Assertions
Prüfen Sie Assertions, indem Sie assert() für das SemanticsNodeInteraction aufrufen, das 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 Komfortfunktionen für die gängigsten Assertions verwenden, z. B. assertExists, assertIsDisplayed und assertTextEquals.
Eine vollständige Liste finden Sie im Spickzettel zum Testen von Compose.
Es gibt auch Funktionen, mit denen Assertions 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 auf einem 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 findest du im Spickzettel zum Testen von Compose.
Matcher
Zum Testen des Compose-Codes stehen verschiedene Matcher zur Verfügung.
Hierarchische Matcher
Mit hierarchischen Abgleichern 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 einige Beispiele für die Verwendung dieser Matcher:
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"))
Eine vollständige Liste finden Sie im Spickzettel zum Testen von Compose.
Zusätzliche Ressourcen
- Apps auf Android testen: Auf der Haupt-Landingpage für Android-Tests finden Sie einen umfassenderen Überblick über die Grundlagen und Techniken des Testens.
- Grundlagen des Testens: Hier finden Sie weitere Informationen zu den grundlegenden Konzepten für das Testen einer Android-App.
- Lokale Tests: Einige Tests können lokal auf Ihrer Workstation ausgeführt werden.
- 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.
- Verschiedene Bildschirmgrößen testen: Da Nutzer so viele verschiedene Geräte zur Verfügung haben, sollten Sie verschiedene Bildschirmgrößen testen.
- Espresso: Obwohl Espresso für ansichtsbasierte UIs gedacht ist, kann es auch für einige Aspekte von Compose-Tests hilfreich sein.