Testy tworzenia wiadomości są domyślnie synchronizowane z Twoim interfejsem użytkownika. Gdy wywołasz twierdzenie lub działanie za pomocą ComposeTestRule
, test jest synchronizowany z wyprzedzeniem i czeka, aż drzewo interfejsu użytkownika będzie nieaktywne.
Zwykle nie musisz nic robić. Istnieją jednak pewne skrajne przypadki które warto wiedzieć.
Po zsynchronizowaniu testu aplikacja Compose przesuwa się w czasie za pomocą wirtualnego zegara. Oznacza to, że testy tworzenia wiadomości nie są przeprowadzane w czasie rzeczywistym i mogą zaliczyć jak najszybciej.
Jeśli jednak nie używasz metod synchronizujących testy, nie będzie można zmiana kompozycji, a interfejs użytkownika będzie wyglądał na 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 funkcji reszta aplikacji.
Wyłączanie automatycznej synchronizacji
Gdy wywołasz za pomocą ComposeTestRule
(np. assertExists()
) twierdzenie lub działanie, test jest synchronizowany z interfejsem tworzenia. W niektórych przypadkach możesz chcieć zatrzymać tę synchronizację i samodzielnie kontrolować zegar. Możesz na przykład kontrolować czas, aby robić dokładne zrzuty ekranu animacji w miejscu, w którym interfejs jest nadal aktywny. Aby wyłączyć automatyczną synchronizację:
ustaw właściwość autoAdvance
w mainClock
na false
:
composeTestRule.mainClock.autoAdvance = false
Zwykle możesz później samodzielnie przesunąć czas. Możesz przejść do następnego etapu dokładnie
klatki z parametrem advanceTimeByFrame()
lub o określonym czasie trwania z
advanceTimeBy()
:
composeTestRule.mainClock.advanceTimeByFrame()
composeTestRule.mainClock.advanceTimeBy(milliseconds)
Nieaktywne zasoby
Compose może synchronizować testy i interfejs użytkownika, aby każde działanie i asercja w stanie bezczynności, odczekania lub przesunięcia zegara w zależności od potrzeb. Jednak niektóre operacji asynchronicznych, których wyniki wpływają na stan UI, można uruchamiać w w tle, nawet jeśli test ich nie zdaje.
Utwórz i zarejestruj te zasoby nieaktywne w testach, aby uwzględnić je przy podejmowaniu decyzji, czy testowana aplikacja jest zajęta czy nie. Nie musisz podejmować żadnych działań, chyba że musisz zarejestrować dodatkowe zasoby niewykorzystywane, 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 Idling Resources firmy Espresso, jeśli chodzi o wskazanie,
testowany obiekt jest bezczynny lub zajęty. Użyj reguły testowej w Compose, aby zarejestrować implementację IdlingResource
.
composeTestRule.registerIdlingResource(idlingResource)
composeTestRule.unregisterIdlingResource(idlingResource)
Synchronizacja ręczna
W niektórych przypadkach musisz zsynchronizować interfejs tworzenia z innymi częściami testu lub aplikacji, którą testujesz.
Funkcja waitForIdle()
czeka, aż funkcja Compose przejdzie w stan bezczynności, ale 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 rysowanie i układ
.
Możesz też przesunąć zegar do momentu spełnienia określonego warunku za pomocą funkcji advanceTimeUntil()
.
composeTestRule.mainClock.advanceTimeUntil(timeoutMs) { condition }
Pamiętaj, że dany warunek powinien sprawdzać stan, na który może wpływać ten zegar (działa tylko w przypadku stanu tworzenia).
Warunki oczekiwania
Wszystkie warunki zależne od pracy zewnętrznej, takie jak wczytywanie danych czy
zmierzyć lub rysować (czyli zmierzyć lub rysować na zewnątrz), należy użyć funkcji
bardziej ogólne pojęcie, np. waitUntil()
:
composeTestRule.waitUntil(timeoutMs) { condition }
Możesz też użyć dowolnego z tych waitUntil
asystentów:
composeTestRule.waitUntilAtLeastOneExists(matcher, timeoutMs)
composeTestRule.waitUntilDoesNotExist(matcher, timeoutMs)
composeTestRule.waitUntilExactlyOneExists(matcher, timeoutMs)
composeTestRule.waitUntilNodeCount(matcher, count, timeoutMs)
Dodatkowe materiały
- Testowanie aplikacji na Androidzie: główne testy na Androidzie. daje szersze spojrzenie na podstawy i techniki testowania.
- Podstawy testowania: więcej informacji o podstawowych koncepcjach testowania aplikacji na Androida.
- Testy lokalne: niektóre testy możesz przeprowadzać lokalnie na swoim komputerze.
- Testy instrumentalne: są dobre. w ramach testów instrumentalnych. Oznacza to, że testy przeprowadzane bezpośrednio na urządzeniu.
- Tryb ciągłej integracji: tryb ciągłej integracji umożliwia zintegrowanie testów z potokiem wdrożeniowym.
- Testowanie różnych rozmiarów ekranu: za pomocą dostępnych dla użytkowników jest bardzo wiele urządzeń, należy przetestować różne urządzenia rozmiarów reklam Google Ads.
- Espresso: chociaż jest przeznaczony do obsługi widoków Interfejsy użytkownika i język espresso mogą też być przydatne w niektórych aspektach funkcji Compose i testowania.