In diesem Thema wird beschrieben, wie Sie von Frameworks bereitgestellte APIs in Tests einbinden, um das Verhalten der einzelnen Fragmente zu bewerten.
Fragmente dienen als wiederverwendbare Container in Ihrer App, mit denen Sie das gleiche Benutzeroberflächenlayout in einer Vielzahl von Aktivitäten und Layoutkonfigurationen präsentieren können. Angesichts der Vielseitigkeit von Fragmenten ist es wichtig, zu überprüfen, ob sie eine einheitliche und ressourceneffiziente Nutzung bieten. Beachten Sie Folgendes:
- Das Fragment sollte nicht von einer bestimmten übergeordneten Aktivität oder einem Fragment abhängig sein.
- Sie sollten die Ansichtshierarchie eines Fragments nur dann erstellen, wenn es für den Nutzer sichtbar ist.
Zum Festlegen der Bedingungen für diese Tests stellt die AndroidX-fragment-testing
-Bibliothek die Klasse FragmentScenario
zum Erstellen von Fragmenten und Ändern ihrer Lifecycle.State
bereit.
Abhängigkeiten deklarieren
Wenn Sie FragmentScenario
verwenden möchten, definieren Sie das Artefakt fragment-testing-manifest
in der Datei build.gradle
Ihrer Anwendung mit debugImplementation
und das Artefakt fragment-testing
mit androidTestImplementation
, wie im folgenden Beispiel gezeigt:
Groovig
dependencies { def fragment_version = "1.8.2" debugImplementation "androidx.fragment:fragment-testing-manifest:$fragment_version" androidTestImplementation "androidx.fragment:fragment-testing:$fragment_version" }
Kotlin
dependencies { val fragment_version = "1.8.2" debugImplementation("androidx.fragment:fragment-testing-manifest:$fragment_version") androidTestImplementation("androidx.fragment:fragment-testing:$fragment_version") }
Für die Testbeispiele auf dieser Seite werden Assertions aus den Espresso- und Truth-Bibliotheken verwendet. Informationen zu anderen verfügbaren Test- und Assertion-Bibliotheken finden Sie unter Projekt für AndroidX Test einrichten.
Fragment erstellen
FragmentScenario
enthält die folgenden Methoden zum Starten von Fragmenten in Tests:
launchInContainer()
zum Testen der Benutzeroberfläche eines Fragments.FragmentScenario
hängt das Fragment an den Root-Ansicht-Controller einer Aktivität an. Andernfalls ist diese Aktivität leer.launch()
zum Testen ohne die Benutzeroberfläche des Fragments.FragmentScenario
hängt diese Art von Fragment an eine leere Aktivität an, die keine Stammansicht hat.
Nach dem Start eines dieser Fragmenttypen bringt FragmentScenario
das zu testende Fragment in einen bestimmten Zustand. Standardmäßig ist dieser Status RESUMED
. Sie können dies jedoch mit dem Argument initialState
überschreiben. Der Status RESUMED
gibt an, dass das Fragment ausgeführt wird und für den Nutzer sichtbar ist. Sie können Informationen zu den UI-Elementen mithilfe von Espresso-UI-Tests auswerten.
Die folgenden Codebeispiele zeigen, wie Sie das Fragment mit den einzelnen Methoden starten:
launchInContainer()-Beispiel
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@Test fun testEventFragment() {
// The "fragmentArgs" argument is optional.
val fragmentArgs = bundleOf(“selectedListItem” to 0)
val scenario = launchFragmentInContainer<EventFragment>(fragmentArgs)
...
}
}
launch()-Beispiel
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@Test fun testEventFragment() {
// The "fragmentArgs" arguments are optional.
val fragmentArgs = bundleOf("numElements" to 0)
val scenario = launchFragment<EventFragment>(fragmentArgs)
...
}
}
Abhängigkeiten angeben
Wenn Ihre Fragmente Abhängigkeiten haben, können Sie Testversionen dieser Abhängigkeiten bereitstellen, indem Sie eine benutzerdefinierte FragmentFactory
für die Methoden launchInContainer()
oder launch()
angeben.
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@Test fun testEventFragment() {
val someDependency = TestDependency()
launchFragmentInContainer {
EventFragment(someDependency)
}
...
}
}
Weitere Informationen zur Verwendung von FragmentFactory
zum Bereitstellen von Abhängigkeiten zu Fragmenten finden Sie unter Fragmentmanager.
Fragment in einen neuen Zustand versetzen
In den UI-Tests Ihrer Anwendung reicht es normalerweise aus, das zu testende Fragment zu starten und mit dem Test im Status RESUMED
zu beginnen. Bei detaillierteren Einheitentests können Sie jedoch auch das Verhalten des Fragments beim Übergang von einem Lebenszyklusstatus in einen anderen bewerten. Den Anfangszustand geben Sie an, indem Sie das Argument initialState
an eine der launchFragment*()
-Funktionen übergeben.
Rufen Sie moveToState()
auf, um dem Fragment einen anderen Lebenszyklusstatus zuzuweisen.
Diese Methode unterstützt die folgenden Status als Argumente: CREATED
, STARTED
, RESUMED
und DESTROYED
. Diese Methode simuliert eine Situation, in der das Fragment oder die Aktivität, die Ihr Fragment enthält, seinen Status aus irgendeinem Grund ändert.
Im folgenden Beispiel wird ein Testfragment mit dem Status INITIALIZED
gestartet und dann in den Status RESUMED
versetzt:
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@Test fun testEventFragment() {
val scenario = launchFragmentInContainer<EventFragment>(
initialState = Lifecycle.State.INITIALIZED
)
// EventFragment has gone through onAttach(), but not onCreate().
// Verify the initial state.
scenario.moveToState(Lifecycle.State.RESUMED)
// EventFragment moves to CREATED -> STARTED -> RESUMED.
...
}
}
Fragment neu erstellen
Wenn Ihre Anwendung auf einem Gerät mit wenig Ressourcen ausgeführt wird, zerstört das System möglicherweise die Aktivität, die Ihr Fragment enthält. In diesem Fall muss Ihre Anwendung das Fragment neu erstellen, wenn der Nutzer zu ihm zurückkehrt.
Rufen Sie recreate()
auf, um diese Situation zu simulieren:
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@Test fun testEventFragment() {
val scenario = launchFragmentInContainer<EventFragment>()
scenario.recreate()
...
}
}
FragmentScenario.recreate()
zerstört das Fragment und seinen Host und erstellt sie dann neu. Wenn die Klasse FragmentScenario
das zu testende Fragment neu erstellt, kehrt das Fragment in den Lebenszyklusstatus zurück, in dem es sich vor dem Löschen befand.
Mit UI-Fragmenten interagieren
Verwenden Sie Espressoaufrufes-Matcher, um UI-Aktionen im zu testenden Fragment auszulösen. So können Sie mit Elementen in der Ansicht interagieren:
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@Test fun testEventFragment() {
val scenario = launchFragmentInContainer<EventFragment>()
onView(withId(R.id.refresh)).perform(click())
// Assert some expected behavior
...
}
}
Wenn Sie eine Methode für das Fragment selbst aufrufen müssen, z. B. auf eine Auswahl im Optionsmenü, können Sie dies sicher tun. Rufen Sie dazu mit FragmentScenario.onFragment()
einen Verweis auf das Fragment ab und übergeben Sie ein FragmentAction
-Objekt:
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@Test fun testEventFragment() {
val scenario = launchFragmentInContainer<EventFragment>()
scenario.onFragment { fragment ->
fragment.myInstanceMethod()
}
}
}
Dialogfeldaktionen testen
FragmentScenario
unterstützt auch das Testen von Dialogfragmenten. Obwohl Dialogfeldfragmente UI-Elemente enthalten, wird ihr Layout in einem separaten Fenster dargestellt und nicht in der Aktivität selbst. Verwenden Sie daher FragmentScenario.launch()
, um Dialogfragmente zu testen.
Im folgenden Beispiel wird der Prozess zum Schließen des Dialogfelds getestet:
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@Test fun testDismissDialogFragment() {
// Assumes that "MyDialogFragment" extends the DialogFragment class.
with(launchFragment<MyDialogFragment>()) {
onFragment { fragment ->
assertThat(fragment.dialog).isNotNull()
assertThat(fragment.requireDialog().isShowing).isTrue()
fragment.dismiss()
fragment.parentFragmentManager.executePendingTransactions()
assertThat(fragment.dialog).isNull()
}
}
// Assumes that the dialog had a button
// containing the text "Cancel".
onView(withText("Cancel")).check(doesNotExist())
}
}