Pierwsze wrażenia
Jeśli wcześniej pracowało się z Playwrightem, poruszanie się po Mobilewright jest bardzo intuicyjne. Wiele koncepcji i rozwiązań działa niemal identycznie. Należą do nich:
- Locator API,
expect,- automatyczne oczekiwanie na elementy,
- przejrzysta struktura testów.
Dzięki temu można szybko rozpocząć pisanie testów, unikając długiego procesu wdrażania się w nowe narzędzie.
Instalacja i konfiguracja
Rozpoczęcie pracy z Mobilewright jest stosunkowo proste. Framework wystarczy dodać do projektu jako zależność npm, a następnie skonfigurować urządzenie fizyczne lub emulator, na którym będą uruchamiane testy.
Przykładowa instalacja:
$ npm install mobilewright
Kolejnym krokiem jest przygotowanie pliku konfiguracyjnego, wskazanie platformy testowej oraz określenie sposobu uruchamiania aplikacji. Po poprawnej konfiguracji pierwszy test można uruchomić bezpośrednio z poziomu terminala.
$ npm run test:android
Sam proces instalacji i przygotowania środowiska nie sprawia większych problemów, szczególnie, jeśli już wcześniej pracowaliśmy z Playwrightem.
Architektura testów
Podczas pracy nad projektem stopniowo wypracowaliśmy następującą strukturę testów:
spec
↓
Screen
↓
Selectors
Takie podejście pozwoliło:
- maksymalnie uprościć testy,
- przenieść całą logikę obsługi ekranów do klas
Screen, - wyraźnie oddzielić selektory od logiki biznesowej,
- znacząco ułatwić utrzymanie testów.
Po refaktoryzacji testy zyskały na czytelności i zaczęły przypominać rzeczywiste scenariusze wykonywane przez użytkownika.
Przykład:
Takie podejście okazało się znacznie praktyczniejsze niż pisanie całej logiki bezpośrednio w plikach spec.
Wyszukiwanie elementów
Mobilewright udostępnia kilka sposobów lokalizowania elementów interfejsu. W wielu przypadkach można korzystać ze standardowych locatorów:

W przypadku pracy z Compose Multiplatform najbardziej stabilnym rozwiązaniem okazało się jednak wykorzystanie contentDescription.
Dlatego, aby uzyskać stabilne i łatwe w utrzymaniu selektory, warto już na etapie implementacji aplikacji dodawać identyfikatory do elementów interfejsu.
Przykład:
Takie podejście znacząco upraszcza tworzenie testów i sprawia, że są one mniej podatne na zmiany w interfejsie. Wsparcie dla automatycznych testów najlepiej uwzględniać już podczas tworzenia aplikacji, zamiast uzupełniać identyfikatory dopiero po rozpoczęciu prac nad testami.
Automatyczne oczekiwanie
Jedną z najbardziej wartościowych funkcji Mobilewright, jest mechanizm automatycznego oczekiwania na elementy. Framework przed wykonaniem akcji sam sprawdza, czy element jest już dostępny i gotowy do interakcji. Dzięki temu w większości przypadków nie ma potrzeby ręcznego implementowania dodatkowych mechanizmów oczekiwania ani stosowania sztucznych opóźnień.
Przykładowo, po przejściu na kolejny ekran nie ma konieczności dodawania własnych pętli sprawdzających dostępność elementów. Wystarczy jedynie wywołać odpowiednią akcję lub asercję, a Mobilewright sam odczeka na gotowość elementu.
Na przykład:

Dzięki temu kod testów pozostaje zwięzły i czytelny, a jednocześnie bardziej odporny na niewielkie opóźnienia wynikające z ładowania danych lub animacji interfejsu.
Ograniczenia podczas pracy z Compose Multiplatform
Wsparcie dla iOS
Podczas pracy nad projektem największym ograniczeniem okazało się wsparcie Compose Multiplatform na systemie iOS. Obecnie Mobilewright bardzo dobrze współpracuje z natywnymi aplikacjami Android oraz aplikacjami wykorzystującymi Jetpack Compose. W przypadku Compose Multiplatform dla iOS wsparcie nadal znajduje się w fazie rozwoju, co potwierdza również oficjalna dokumentacja frameworka.
Oznacza to, że niektóre testy da się uruchomić również na iOS, jednak ich stabilność jest wyraźnie niższa niż na Androidzie. Zdarzało się, że ten sam scenariusz testowy przechodził poprawnie kilka razy z rzędu, a następnie kończył się błędem bez wprowadzania jakichkolwiek zmian w aplikacji lub w kodzie testów.
Dodatkowo, nie wszystkie elementy interfejsu Compose Multiplatform są poprawnie udostępniane dla mechanizmów Accessibility wykorzystywanych przez Mobilewright. Powoduje to trudności z lokalizowaniem niektórych elementów oraz wpływa na stabilność testów. Z tego względu na obecnym etapie rozwoju frameworka Mobilewright znacznie lepiej sprawdza się podczas automatyzacji aplikacji Compose Multiplatform na Androidzie niż na iOS. Aktualny poziom wsparcia poszczególnych technologii został przedstawiony w dokumentacji Mobilewright.
Brak inspektora drzewa elementów
Jednym z brakujących udogodnień podczas pracy z Mobilewright okazał się pełnoprawny inspektor drzewa elementów.
Mobilewright udostępnia metodę viewTree(), która zwraca informacje o elementach dostępnych dla mechanizmów Accessibility. Każdy element zawiera między innymi jego typ, etykietę (label), tekst (text), współrzędne (bounds) oraz informację o widoczności.

Fragment rzeczywistego wyniku metody viewTree() w Mobilewright.
Jak widać na powyższym przykładzie, wynik jest prezentowany w terminalu jako lista obiektów. Pozwala to sprawdzić, jakie elementy są dostępne dla frameworka, jednak nie zapewnia wygodnego, graficznego widoku hierarchii interfejsu.
W konsekwencji analiza złożonych ekranów oraz debugowanie problemów z locatorami jest przez to bardziej czasochłonne. Trudniej też szybko określić, czy element nie został znaleziony z powodu nieprawidłowego locatora, czy dlatego, że nie został poprawnie udostępniony przez aplikację.
Widoczne na zrzucie wartości label, takie jak title lub currency_item_EUR_PLN, odpowiadają właściwościom contentDescription zdefiniowanym w aplikacji Compose Multiplatform.
Praca z polami tekstowymi
Podczas testowania aplikacji Compose Multiplatform napotkałem pewną specyfikę działania metody fill(). Standardowe wywołanie:
await field.fill("new value");
nie zawsze zachowywało się zgodnie z oczekiwaniami. W niektórych polach tekst nie był zastępowany nową wartością – nowy tekst był jedynie dopisywany do już istniejącego. Dodatkowo kursor nie zawsze ustawiał się automatycznie na końcu pola, co utrudniało usuwanie poprzedniej zawartości.
Aby zapewnić stabilność testów, przygotowałem własną pomocniczą metodę czyszczenia pola przed wprowadzeniem nowego ciągu znaków.
Algorytm wygląda następująco:
- Odczytanie aktualnej wartości pola.
- Ustawienie kursora na końcu tekstu.
- Usunięcie wszystkich dotychczasowych znaków.
- Wprowadzenie nowej wartości.
Przykładowa implementacja:
Po zastosowaniu takiego rozwiązania praca z polami tekstowymi stała się znacznie bardziej stabilna.
Podsumowanie
Po kilku tygodniach pracy z Mobilewright uważam go za interesujący framework z dużym potencjałem, szczególnie dla osób, które mają już doświadczenie w pracy z Playwrightem.
Do największych zalet zaliczyłbym:
- proste i czytelne API,
- niski próg wejścia dla osób znających Playwrighta,
- wygodny Locator API,
- automatyczne oczekiwanie na elementy,
- możliwość zbudowania przejrzystej i łatwej w utrzymaniu architektury testów.
Podczas pracy nad aplikacją Compose Multiplatform napotkałem również pewne ograniczenia. Do najbardziej odczuwalnych należały: niepełne wsparcie systemu iOS, brak wygodnego inspektora drzewa elementów oraz konieczność przygotowania własnego rozwiązania do stabilnej obsługi pól tekstowych.
Mimo tych utrudnień praca z Mobilewright pozwoliła na przygotowanie zestawu testów automatycznych. Jednocześnie zdobyte doświadczenia pokazały, że podczas pracy z Compose Multiplatform warto odpowiednio przygotować aplikację do automatyzacji, między innymi poprzez dodawanie contentDescription do elementów interfejsu.
Przedstawione wnioski odnoszą się do konkretnego przypadku wykorzystania Mobilewright w projekcie Compose Multiplatform. Część opisanych ograniczeń może zostać wyeliminowana w kolejnych wydaniach frameworka.
Vladyslav Stashko



