Automatyzacja testów interfejsu

Testowanie interakcji użytkowników pomaga zadbać o to, aby podczas korzystania z aplikacji nie pojawiały się nieoczekiwane efekty i nie są one zadowoleni z korzystania z niej. Jeśli chcesz sprawdzić, czy interfejs aplikacji działa prawidłowo, wyrób sobie nawyk tworzenia testów interfejsu użytkownika.

Jednym ze sposobów testowania interfejsu użytkownika jest wykonanie przez testera zestawu operacji na użytkowniku w aplikacji docelowej i sprawdzenie, czy działa ona prawidłowo. Takie ręczne podejście może być jednak czasochłonne i podatne na błędy. Efektywniejszym sposobem jest napisanie testów interfejsu tak, aby działania użytkowników były wykonywane w sposób automatyczny. Zautomatyzowane podejście pozwala przeprowadzać testy szybko i niezawodnie w powtarzalny sposób.

Testy interfejsu uruchamiają aplikację (lub jej część), symulują interakcje użytkownika i sprawdzają, czy aplikacja prawidłowo zareagowała. Są to testy integracji, które mogą mieć różny zakres: od weryfikacji działania małego komponentu po duży test nawigacji, który obejmuje całą ścieżkę użytkownika. Przydają się one do sprawdzania zgodności z różnymi poziomami interfejsów API i urządzeń fizycznych oraz sprawdzania pod kątem regresji.

Testy interfejsu użytkownika w Android Studio

Aby przeprowadzić testy interfejsu użytkownika w Android Studio, musisz zaimplementować kod testowy w osobnym folderze testowym Androida – src/androidTest/java. Wtyczka Androida dla Gradle kompiluje aplikację testową na podstawie kodu testowego, a potem wczytuje ją na tym samym urządzeniu co aplikacja docelowa. W kodzie testowym możesz używać platform testowania interfejsu do symulowania interakcji użytkowników w aplikacji docelowej, aby wykonywać zadania testowe obejmujące określone scenariusze użycia.

Platformy Jetpack

Jetpack zawiera różne platformy udostępniające interfejsy API do pisania testów interfejsu:

  • Platforma testowania Espresso (Android 4.0.1, interfejs API na poziomie 14 lub wyższym) udostępnia interfejsy API do pisania testów interfejsu, które symulują interakcje użytkowników z obiektami View w ramach jednej aplikacji docelowej. Główną zaletą używania Espresso jest to, że umożliwia ono automatyczną synchronizację testów z interfejsem testowanej aplikacji. Espresso wykrywa, kiedy wątek główny jest nieaktywny, dzięki czemu może uruchomić polecenia testowe w odpowiednim czasie, co zwiększa wiarygodność testów.
  • Jetpack Compose (Android 5.0, interfejs API na poziomie 21 lub wyższym) udostępnia zestaw testowych interfejsów API, które umożliwiają uruchamianie ekranów i komponentów Compose oraz korzystanie z nich. Interakcje z elementami tworzenia są synchronizowane z testami i mają pełną kontrolę nad czasem, animacjami i rekompozycją.
  • UI Automator (Android 4.3, interfejs API na poziomie 18 lub wyższym) to platforma do testowania interfejsu użytkownika, która sprawdza się w różnych aplikacjach w systemie i zainstalowanych aplikacjach. Interfejsy API Automator pozwalają wykonywać operacje, takie jak otwieranie menu Ustawienia czy Menu z aplikacjami na urządzeniu testowym.
  • Robolectric (Android 4.1, poziom interfejsu API 16 lub wyższy) umożliwia tworzenie testów lokalnych, które będą przeprowadzane na stacji roboczej lub w środowisku ciągłej integracji w zwykłej maszynie JVM zamiast w emulatorze lub urządzeniu. Może używać testowych interfejsów API Espresso lub Compose do interakcji z komponentami interfejsu.

Niestabilne działanie i synchronizacja

Asynchroniczna natura aplikacji i platform mobilnych często sprawia, że trudno jest stworzyć wiarygodne i powtarzalne testy. Po wstrzykiwaniu zdarzenia użytkownika platforma testów musi poczekać, aż aplikacja na nie zareaguje. Może to obejmować zmianę tekstu na ekranie lub pełne odtworzenie aktywności. Jeśli test nie ma deterministycznego zachowania, jest on niestabilny.

Nowoczesne platformy, takie jak Compose czy Espresso, zostały zaprojektowane z myślą o testowaniu, dzięki czemu istnieje pewna gwarancja, że interfejs użytkownika będzie nieaktywny przed kolejnym testowym działaniem lub asercją. Na przykład oznacza to synchronizację.

Testowanie synchronizacji

Problemy nadal mogą się pojawiać przy uruchamianiu operacji asynchronicznych lub operacji w tle, których nie znamy, takich jak wczytywanie danych z bazy danych lub wyświetlanie nieskończonych animacji.

schemat procesu pokazujący pętlę, która przed zaliczeniem testu sprawdza, czy aplikacja jest bezczynna
Rysunek 1. Testowanie synchronizacji.

Aby zwiększyć niezawodność pakietu testowego, możesz zainstalować sposób śledzenia operacji w tle, taki jak zasoby Espresso Idling. Możesz też zastąpić moduły wersji testowych, których można używać jako zapytań o nieaktywność lub które usprawniają synchronizację, na przykład TestDispatcher dla współprogramów lub RxIdler dla RxJava.

Diagram przedstawiający błąd testu, gdy synchronizacja polega na oczekiwaniu przez określony czas
Rysunek 2. Stosowanie snu w testach prowadzi do powolnych lub niepewnych wyników.

Konfiguracja architektury i testów

Architektura aplikacji powinna umożliwiać testom zastąpienie jej części na potrzeby testowania podwójnej precyzji. Używaj bibliotek udostępniających narzędzia ułatwiające testowanie. Możesz na przykład zastąpić moduł repozytorium danych jego działającą w pamięci wersją, która dostarcza do testu fałszywe, deterministyczne dane.

Tworzenie i testowanie diagramów architektonicznych. Diagram produkcyjny pokazuje lokalne i zdalne źródła danych dostarczające dane do repozytorium, które z kolei dostarcza je asynchronicznie do interfejsu użytkownika. Diagram testowania przedstawia fałszywe repozytorium, które udostępnia swoje dane synchronicznie do interfejsu użytkownika.
Rysunek 3. Testowanie interfejsu przez zastąpienie jego zależności fałszywymi.

Zalecanym sposobem włączenia tej funkcji jest wstrzykiwanie zależności. Możesz utworzyć własny system ręcznie, ale zalecamy skorzystanie z platformy DI, takiej jak Hilt.

Dlaczego testy automatyczne?

Aplikacja na Androida może być kierowana na tysiące różnych urządzeń, o różnych poziomach interfejsów API i formatach. Wysoki poziom dostosowania, jaki zapewnia system operacyjny, oznacza, że może się ona nieprawidłowo renderować lub ulec awarii na niektórych urządzeniach.

Testy interfejsu umożliwiają testowanie zgodności, które pozwala zweryfikować działanie aplikacji w różnych kontekstach. Testy UI możesz przeprowadzić na urządzeniach, które różnią się od siebie tymi elementami:

  • Poziom API: 21, 25 i 30.
  • Język: angielski, arabski i chiński.
  • Orientacja: pionowa lub pozioma.

Poza tym aplikacje powinny sprawdzać działanie innych aplikacji. Przetestuj to na tabletach, urządzeniach składanych i innych urządzeniach.

Dodatkowe materiały

Więcej informacji o tworzeniu testów interfejsu użytkownika znajdziesz w tych materiałach.

Dokumentacja

Ćwiczenia z programowania