Testy tworzenia wiadomości są domyślnie synchronizowane z Twoim interfejsem użytkownika. Gdy wywołasz asercję lub działanie za pomocą ComposeTestRule
, test zostanie zsynchronizowany wcześniej, w oczekiwaniu, aż drzewo interfejsu będzie nieaktywne.
Zazwyczaj nie musisz nic robić. Istnieją jednak skrajne przypadki, o których warto wiedzieć.
Podczas synchronizowania testu aplikacja Compose jest coraz bardziej zaawansowana w czasie przy użyciu zegara wirtualnego. Oznacza to, że testy tworzenia wiadomości nie są przeprowadzane w czasie rzeczywistym i mogą zaliczyć jak najszybciej.
Jeśli jednak nie użyjesz metod, które synchronizują testy, nie nastąpi zmiana kompozycji, a interfejs będzie wyświetlany jako wstrzymany.
@Test
fun counterTest() {
val myCounter = mutableStateOf(0) // State that can cause recompositions.
var lastSeenValue = 0 // Used to track recompositions.
composeTestRule.setContent {
Text(myCounter.value.toString())
lastSeenValue = myCounter.value
}
myCounter.value = 1 // The state changes, but there is no recomposition.
// Fails because nothing triggered a recomposition.
assertTrue(lastSeenValue == 1)
// Passes because the assertion triggers recomposition.
composeTestRule.onNodeWithText("1").assertExists()
}
Pamiętaj, że to wymaganie dotyczy tylko hierarchii w usłudze Compose, a nie pozostałej części aplikacji.
Wyłączanie automatycznej synchronizacji
Gdy wywołasz potwierdzenie lub działanie za pomocą interfejsu ComposeTestRule
, na przykład assertExists()
, test zostanie zsynchronizowany z interfejsem tworzenia wiadomości. W niektórych przypadkach możesz chcieć zatrzymać tę synchronizację i samodzielnie ustawić zegar. Możesz na przykład kontrolować czas, aby zrobić dokładne zrzuty ekranu animacji w miejscach, w których interfejs użytkownika jest nadal zajęty. Aby wyłączyć automatyczną synchronizację, ustaw właściwość autoAdvance
w narzędziu mainClock
na wartość false
:
composeTestRule.mainClock.autoAdvance = false
Zwykle możesz później samodzielnie przesunąć czas. Możesz przewinąć do przodu dokładnie o 1 klatkę za pomocą funkcji advanceTimeByFrame()
lub o określony czas trwania w narzędziu advanceTimeBy()
:
composeTestRule.mainClock.advanceTimeByFrame()
composeTestRule.mainClock.advanceTimeBy(milliseconds)
Nieaktywne zasoby
Usługa Compose może synchronizować testy i interfejs użytkownika, aby każde działanie i potwierdzenie było wykonywane w stanie bezczynności, oczekiwaniem lub przedłużeniem zegara odpowiednio do potrzeb. Jednak niektóre operacje asynchroniczne, których wyniki wpływają na stan UI, mogą być wykonywane w tle, gdy test ich nie wie.
Utwórz i zarejestruj te nieaktywne zasoby w teście, aby były one brane pod uwagę podczas podejmowania decyzji o tym, czy testowana aplikacja jest zajęta czy bezczynna. Nie musisz niczego robić, chyba że musisz zarejestrować dodatkowe nieaktywne zasoby, na przykład jeśli uruchomisz zadanie w tle, które nie jest zsynchronizowane z Espresso lub Compose.
Ten interfejs API jest bardzo podobny do raportu Idling Resources w Espresso, który wskazuje, czy testowany obiekt jest bezczynny czy zajęty. Użyj reguły testowej tworzenia wiadomości, aby zarejestrować implementację obiektu IdlingResource
.
composeTestRule.registerIdlingResource(idlingResource)
composeTestRule.unregisterIdlingResource(idlingResource)
Synchronizacja ręczna
W niektórych przypadkach musisz zsynchronizować interfejs tworzenia wiadomości z innymi częściami testu lub testowaną aplikacją.
Funkcja waitForIdle()
czeka, aż funkcja tworzenia wiadomości będzie nieaktywna, ale jej działanie zależy od właściwości autoAdvance
:
composeTestRule.mainClock.autoAdvance = true // Default
composeTestRule.waitForIdle() // Advances the clock until Compose is idle.
composeTestRule.mainClock.autoAdvance = false
composeTestRule.waitForIdle() // Only waits for idling resources to become idle.
W obu przypadkach waitForIdle()
czeka też na oczekujące przebiegi renderowania i układu.
Możesz też przyspieszyć zegar, dopóki określony warunek nie zostanie spełniony za pomocą funkcji advanceTimeUntil()
.
composeTestRule.mainClock.advanceTimeUntil(timeoutMs) { condition }
Pamiętaj, że dany warunek powinien sprawdzać stan, na który zegar może mieć wpływ (działa tylko ze stanem tworzenia).
Poczekaj na warunki
W przypadku wszystkich warunków zależnych od pracy zewnętrznej, takich jak wczytywanie danych czy pomiar lub rysowanie Androida (czyli pomiar lub rysowanie na zewnątrz w usłudze Compose), należy stosować bardziej ogólną koncepcję, taką jak waitUntil()
:
composeTestRule.waitUntil(timeoutMs) { condition }
Możesz też użyć dowolnego z pomocy narzędzia waitUntil
:
composeTestRule.waitUntilAtLeastOneExists(matcher, timeoutMs)
composeTestRule.waitUntilDoesNotExist(matcher, timeoutMs)
composeTestRule.waitUntilExactlyOneExists(matcher, timeoutMs)
composeTestRule.waitUntilNodeCount(matcher, count, timeoutMs)
Dodatkowe materiały
- Testowanie aplikacji na Androida: główna strona docelowa testowania na Androida zawiera szersze omówienie podstaw i technik testowania.
- Podstawy testowania: dowiedz się więcej o podstawowych założeniach testowania aplikacji na Androida.
- Testy lokalne: niektóre testy możesz przeprowadzić lokalnie, na swojej stacji roboczej.
- Testy instrumentowane: warto też przeprowadzać testy instrumentowane. Chodzi o testy przeprowadzane bezpośrednio na urządzeniu.
- Tryb ciągłej integracji: tryb ciągłej integracji umożliwia integrację testów z potokiem wdrażania.
- Przetestuj różne rozmiary ekranów: warto przetestować różne rozmiary ekranów w przypadku dużej liczby urządzeń dostępnych dla użytkowników.
- Espresso: chociaż wiedza o Espresso jest przeznaczona dla interfejsu opartego na widoku, może okazać się przydatna w niektórych aspektach testowania funkcji Compose.