Z tego artykułu dowiesz się, jak uwzględnić w testach interfejsy API udostępniane przez platformę aby ocenić zachowanie poszczególnych fragmentów.
Fragmenty kodu to kontenery wielokrotnego użytku w aplikacji, dzięki którym: ten sam układ interfejsu w wielu różnych działaniach konfiguracji układu. Ze względu na uniwersalność fragmentów ważne jest, w celu potwierdzenia, że działają w sposób spójny i oszczędny. Uwaga:
- Fragment nie powinien być uzależniony od konkretnej aktywności nadrzędnej ani fragment.
- Nie należy tworzyć hierarchii widoku fragmentu, chyba że fragment będą widoczne dla użytkownika.
Aby skonfigurować warunki przeprowadzania testów, AndroidX
Biblioteka fragment-testing
udostępnia
FragmentScenario
.
do tworzenia fragmentów i zmieniania ich
Lifecycle.State
Deklarowanie zależności
Aby użyć funkcji FragmentScenario
, zdefiniuj artefakt fragment-testing-manifest
w
pliku build.gradle
aplikacji za pomocą debugImplementation
, a artefakt fragment-testing
używający androidTestImplementation
, jak pokazano w
następujący przykład:
Odlotowe
dependencies { def fragment_version = "1.8.3" debugImplementation "androidx.fragment:fragment-testing-manifest:$fragment_version" androidTestImplementation "androidx.fragment:fragment-testing:$fragment_version" }
Kotlin
dependencies { val fragment_version = "1.8.3" debugImplementation("androidx.fragment:fragment-testing-manifest:$fragment_version") androidTestImplementation("androidx.fragment:fragment-testing:$fragment_version") }
Przykłady testowania na tej stronie wykorzystują asercje z Espresso i Truth. Informacje na temat: inne dostępne biblioteki testowania i asercji, zobacz Skonfiguruj projekt na potrzeby Testu AndroidX.
Tworzenie fragmentu
FragmentScenario
udostępnia te metody uruchamiania fragmentów
w testach:
launchInContainer()
do testowania interfejsu użytkownika fragmentu.FragmentScenario
dołącza makro do głównego kontrolera widoku aktywności. Zawiera aktywność jest pusty.launch()
do testowania bez użycia interfejsu użytkownika fragmentu.FragmentScenario
dołącza ten typ fragmentu do pustego działania, które nie oznacza, i mamy widok główny.
Po uruchomieniu jednego z tych typów fragmentów FragmentScenario
powoduje uruchomienie tagu
w trakcie testowania do określonego stanu. Domyślnie ten stan to RESUMED
,
ale możesz to zastąpić argumentem initialState
. RESUMED
stan
wskazuje, że fragment jest aktywny i widoczny dla użytkownika. Możesz ocenić
informacje o jego elementach interfejsu za pomocą interfejsu Espresso
Poniższe przykłady kodu pokazują, jak uruchomić fragment przy użyciu poszczególnych metod:
PrzykładlaunchInContainer()
@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() – przykład
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@Test fun testEventFragment() {
// The "fragmentArgs" arguments are optional.
val fragmentArgs = bundleOf("numElements" to 0)
val scenario = launchFragment<EventFragment>(fragmentArgs)
...
}
}
Podaj zależności
Jeśli Twoje fragmenty są zależne od zależności, możesz przesłać wersje testowe
te zależności, dodając niestandardowy element FragmentFactory
do funkcji
launchInContainer()
lub launch()
.
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@Test fun testEventFragment() {
val someDependency = TestDependency()
launchFragmentInContainer {
EventFragment(someDependency)
}
...
}
}
Więcej informacji o używaniu właściwości FragmentFactory
do przekazywania
zależności we fragmentach, zobacz
Menedżer fragmentów.
Przenieś fragment do nowego stanu
W testach interfejsu aplikacji zwykle wystarczy uruchomić dany fragment.
w trakcie testowania i rozpocząć testowanie od stanu RESUMED
. Szczegółowo
testów jednostkowych, możesz też jednak ocenić zachowanie fragmentu
podczas przechodzenia
z jednego stanu cyklu życia do drugiego. Możesz określić
stanu początkowego, przekazując argument initialState
do dowolnej
launchFragment*()
.
Aby przekierować fragment do innego stanu cyklu życia, wywołaj
moveToState()
Ta metoda obsługuje jako argumenty następujące stany: CREATED
,
STARTED
, RESUMED
i DESTROYED
. Ta metoda symuluje sytuację
gdzie fragment lub działanie zawierające Twój fragment zmienia swój
stanu z dowolnego powodu.
Poniższy przykład uruchamia fragment testowy w stanie INITIALIZED
i
i zmienia go do stanu RESUMED
:
@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.
...
}
}
Odtwórz fragment
Jeśli aplikacja działa na urządzeniu, na którym brakuje zasobów, system
może zniszczyć aktywność zawierającą Twój fragment. Ta sytuacja
wymaga od aplikacji odtworzenia fragmentu, gdy użytkownik do niego wróci.
Aby zasymulować taką sytuację, zadzwoń pod numer recreate()
:
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@Test fun testEventFragment() {
val scenario = launchFragmentInContainer<EventFragment>()
scenario.recreate()
...
}
}
FragmentScenario.recreate()
niszczy fragment i jego hosta, a następnie odtwarza je. Gdy
Klasa FragmentScenario
odtworzy testowany fragment, czyli fragment
wraca do stanu cyklu życia sprzed zniszczenia.
Interakcja z fragmentami interfejsu
Aby aktywować działania interfejsu dla testowanego fragmentu, użyj funkcji Dopasowania widoku Espresso aby wchodzić w interakcję z elementami w widoku:
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@Test fun testEventFragment() {
val scenario = launchFragmentInContainer<EventFragment>()
onView(withId(R.id.refresh)).perform(click())
// Assert some expected behavior
...
}
}
Jeśli musisz wywołać metodę na samym fragmencie, np. odpowiedzieć
możesz to zrobić bezpiecznie, pobierając
odwołanie do fragmentu za pomocą funkcji
FragmentScenario.onFragment()
i przekazanie
FragmentAction
:
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@Test fun testEventFragment() {
val scenario = launchFragmentInContainer<EventFragment>()
scenario.onFragment { fragment ->
fragment.myInstanceMethod()
}
}
}
Testuj działania w oknie dialogowym
FragmentScenario
obsługuje też testowanie
fragmenty okien. Chociaż fragmenty dialogów
elementów interfejsu, ich układ wyświetla się w osobnym oknie,
niż w samej aktywności. Z tego powodu użyj funkcji
FragmentScenario.launch()
, aby przetestować fragmenty okien.
Ten przykład testuje proces zamykania okna:
@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())
}
}