Testy tworzenia są domyślnie synchronizowane z 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ć. Należy jednak pamiętać o pewnych skrajnych przypadkach.
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ć je jak najszybciej.
Jeśli jednak nie używasz metod synchronizowania testów, nie nastąpi ponowne złożenie i interfejs 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 sekcji Tworzenie, a nie reszty 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 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 mainClock
na false
:
composeTestRule.mainClock.autoAdvance = false
Zazwyczaj będziesz to robić samodzielnie. Możesz przesunąć o dokładnie jeden kadr za pomocą advanceTimeByFrame()
lub o określony czas za pomocą advanceTimeBy()
:
composeTestRule.mainClock.advanceTimeByFrame()
composeTestRule.mainClock.advanceTimeBy(milliseconds)
Nieaktywne zasoby
Compose może synchronizować testy i interfejs użytkownika, tak aby każde działanie i założenie było wykonywane w stanie bezczynności, oczekując lub przesuwając zegar w miarę potrzeby. 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 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 Zasobów nieczynności w Espresso, które wskazują, czy testowany obiekt jest nieczynny czy zajęty. Użyj reguły testowej w komponencie 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 przechodzenie przez etapy generowania i rozmieszczania elementów.
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).
Oczekiwanie na warunki
W przypadku każdego warunku, który zależy od pracy zewnętrznej, np. wczytywania danych lub funkcji pomiaru lub rysowania w Androidzie (czyli pomiaru lub rysowania zewnętrznego w Compose), należy użyć bardziej ogólnego pojęcia, takiego jak 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 Androida: główna strona z informacjami o testowaniu na Androida zawiera więcej informacji o podstawach i technikach testowania.
- Podstawy testowania: dowiedz się więcej o podstawowych koncepcjach testowania aplikacji na Androida.
- Testy lokalne: niektóre testy możesz przeprowadzić lokalnie, na swojej stacji roboczej.
- Testy z instrumentacją: warto też przeprowadzać testy z instrumentacją. Chodzi o testy, które są wykonywane 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: ze względu na dużą liczbę urządzeń dostępnych dla użytkowników, należy przeprowadzić testy na różnych rozmiarach ekranu.
- Espresso: chociaż jest ono przeznaczone do interfejsów użytkownika opartych na widokach, znajomość Espresso może być przydatna w niektórych aspektach testowania w Compose.