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.