Testy UI
Testy intregracyjne
są przeprowadzane w celu wykrycia błędów zachodzących w interakcji pomiędzy integrowanymi interfejsami systemu i polegają na testowaniu reakcji na wywołane zdarzenia oraz wymianie danych między testowanymi elementami. Wykonywane są na wielu poziomach testowania i dotyczą całego obszaru integracji (funkcjonalności, moduły, systemy). Realizacją testów integracyjnych w Android są testy UI
(testy interfejsu użytkownika
) polegające na przeprowadzeniu zestawu ciągu operacji w docelowej aplikacji z punktu widzenia użytkownika. Ręczne testy
przeprowadzane przez testera choć ważne są jednak obciążone sporym nakładem czasowym i podatne na błędy, dlatego warto dążyć do automatyzacji testów UI. Instrumentalne automatyczne testy
interfejsu użytkownika mogą dotyczyć jednej aplikacji lub interakcji między aplikacjami czy też aplikacją i systemem. Przykładem biblioteki przeznaczonej do testów UI obejmujących jedną aplikację jest Espresso
, a dla interakcji między aplikacjami i systemem np. UI Automator
. Jako alternatywę można rozważyć biblioteki Robotium
lub Appium
. Interfejs użytkownika może być również testowany pod względem wydajności dzięki takim narzędziom jak dumbsys
i systrace
.
Charakterystyka
Testy jednej aplikacji weryfikują zachowanie docelowej aplikacji w stosunku do przeprowadzonych ustalonych działań lub wprowadzenia danych w ekranie aplikacji (Aktywności
) przez użytkownika. Espresso w sposób automatyczny umożliwia przeprowadzanie symulacji akcji użytkownika w aplikacji oraz sprawdzenie oczekiwanego rezultatu po stronie UI co może przełożyć się na zwiększenie jakości User Experience
. Udostępnione podstawowe API jest niewielkie, proste, intuicyjne i oparte jest o interakcję oraz asercje stanów widoków. Przeznaczone jest do operowania na konkretnych widokach oraz wybranych elementach kolekcji widoków. Espresso działa szybko i zapewnia właściwe zarządzanie wątkiem głównym dzięki czemu uruchamia polecenia testowe we właściwym czasie co zwalnia programistę z obowiązku tworzenia tymczasowych obejść. Aby uniknąć nieoczekiwanych rezultatów i błędów w przeprowadzanych testach rekomendowane jest wyłączenie (na testowanym urządzeniu fizycznym lub wirtualnym) animacji systemowych dostępnych w opcjach programisty (animacje okien, animacje przejścia, czas animacji).
Przykład
Na podstawie AktywnościMainActivity
zostaną przedstawione możliwości implementacji automatycznych testów UI w Espresso.
Metoda testowa
Wykorzystanie zasady ActivityTestRule
w klasie testowej sprawia, że aktywność jest uruchamiana przed startem każdego testu i zamykana po jego zakończeniu, redukując tym samym ilość powtarzającego się kodu co w przypadku testów Espresso jest znacznym uproszczeniem. Metoda testowa w Espresso przeprowadza operacje na widokach aktywności. Najpierw uzyskuje dostęp do komponentu interfejsu graficznego, następnie symuluje interakcje użytkownika z widokiem i na końcu weryfikuje jego stan z oczekiwanym. Aby jeszcze bardziej uprościć tworzenie testów warto wykorzystać Hamcrest
, który oferuję elastyczną składnie zapytań.
Dostęp do widoków
Aby znaleźć widok należy wywołać onView
lub dla kolekcji widoków onData
oraz przekazać zapytanie (matcher
) wskazujące na oczekiwany widok np. na podstawie id (withId
), zawartości (withText
, containsString
) czy typu (instanceOf
). W rezultacie zostanie zwrócony obiekt typu ViewInteraction
lub DataInteraction
(dla kolekcji widoków), który umożliwia przeprowadzenie interakcji z widokiem. Trzeba mieć jednak na uwadze, że Android nie gwarantuje unikatowych ID elementów co w przypadku sytuacji używania tego samego ID przez kilka różnych widoków może powodować problemy (wyrzucenie wyjątku AmbiguousViewMatcherException
). W takich sytuacjach warto wykorzystywać kombinacje dopasowań za pomocą metody allOf
. W przypadku kolekcji widoków takich jak np. ListView
nie ma pewności uzyskania żądanego widoku za pomocą onView
(tylko część elementów jest widoczna) dlatego dostęp powinien odbywać się poprzez dane za pomocą onData
. Espresso potrafi również poradzić sobie widokami typu WebView
.
Przeprowadzenie akcji
Uruchomienie akcji następuje poprzez wyołanie metody perform
klasy ViewInteraction
lub DataInteraction
w zależności od rodzaju elementu oraz przekazanie obiektów typu ViewAction
jako argumentów. Akcje jakie można wykonać to m.in. click
, typeText
, scrollTo
, pressKey
, clearText
. Ponadto jeśli podejmowana akcja dotyczy intencji (Intent
) można wykorzystać zasadę IntentsTestRule
, która waliduję intencje wysłane przez testowane aplikację oraz metody weryfikujące intended
dla startActivity
i intending
dla startActivityForResult
.
Weryfikacja rezultatu
Sprawdzanie stanu widoków następuje poprzez wyołanie metody check
klasy ViewInteraction
lub DataInteraction
w zależności od rodzaju elementu oraz przekazanie obiektów typu ViewAssertion
jako argumentów. Asercje jakie można wykonać to m.in. doesNotExist
, matches
, selectedDescendentsMatch
.
UI Automator
Testy przeprowadzane w UI Automator
pozwalają na weryfikację zachowania testowanej w aplikacji w interakcjach z innymi aplikacjami lub komponentami systemu. Przebiegają wg podobnego scenariusza co testy w Espresso
, tzn. znajdowany jest widok, wykonywane są akcje i finalnie następuje sprawdzenie poprawności oczekiwanego stanu. Na wstępie jednak trzeba uzyskać dostęp do testowanego urządzenia poprzez instancję UiDevice
dzięki czemu możliwe jest znajdowanie i operowanie na widokach oraz manipulowanie stanem urządzania. Dobrą praktyką jest rozpoczynanie testów od głównego ekranu systemowego.
Aby otrzymać dostęp do komponentów widoków aplikacji (widocznych na ekranie) należy uzyskać instancję typu UiObject
wywołując metodę findObject
na obiekcie UiDevice
przekazując jako argument odpowiedni UiSelector
konstruowany na podstawie m.in. id (resourceId
), zawartości (text
) czy nazwy klasy obiektu widoku (className
). O ile komplet informacji nt widoków testowanej aplikacji dostępny jest z poziomu kodu to w przypadku zewnętrznych aplikacji i komponentów systemu już niekoniecznie. W takim przypadku można posłużyć się narzędziem UI Automator Viewer
dostępnym w Android Studio
. Akcje jakie można wykonać to m.in. click
, dragTo
, setText
, swipeUp
.
Symulowanie interakcji z elementami kolekcji lub komponentami typu scrollable może odbywać się przy użyciu klas UiCollection
i UiScrollable
.
Android Test Orchestrator
Wykonywanie testów interfejsu użytkownika w Android od czasu do czasu narażone jest na występowanie błędów z niespodziewanym zatrzymanie całego zestawu testowego oraz ze wzajemnym nakrywaniem się testów (np. test się zakończył, ale żądane operacje w tle nadal trwa co może mieć wpływ na kolejne testy). Wykorzystanie mechanizmu bezczynnych zasobów
(idling resources
) pozwala w kontrolowany sposób przeprowadzić operacje asynchroniczną, której wyniki wpływają na kolejne operacje w teście co jednak nie rozwiązuje całkowicie wspomnianych problemów. Z pomocą przychodzi narzędzie Android Test Orchestrator
, które umożliwia wykonanie każdego testu na własnej odseparowanej instancji AndroidJUnitRunner
.
Espresso Test Recorder
Narzędzie Espresso Test Recorder
umożliwia tworzenie testów UI w Espresso
poprzez rejestrowanie akcji oraz tworzenie asercji w graficznym panelu bez ręcznego pisania kodu. Aby nagrać test należy w Android Studio
wybrać opcję Run/Record Espresso Test
, uruchomić aplikację na wskazanym urządzeniu lub emulatorze oraz ręcznie wykonać akcje użytkownika w aplikacji dodając asercje dla stanu widoków. Nagrany test można zapisać do nowej klasy testowej i uruchomić tak samo jak każdy test instrumentalny. Tworzenie testów przy pomocy Espresso Test Recorder jest powolne, a asercje ograniczone do weryfikowania tekstu i istnienia widoku.