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.