Testy automatyczne aplikacji webowych zrobiły w ostatnich latach ogromny krok do przodu.
Mamy Playwrighta, mamy Cypressa, mamy całkiem wygodne API, auto-waiting, dobre raporty, trace viewer, sensowną pracę z locatorami i coraz lepsze wsparcie w CI/CD.
A potem człowiek przechodzi do testów mobilnych i bardzo często ma wrażenie, jakby cofnął się kilka lat wstecz.
Konfiguracja emulatorów, capabilities, problemy z selektorami, niestabilne testy, różnice między Androidem i iOS, XPath-y, czekanie na animacje, dziwne błędy środowiskowe. Oczywiście da się z tym pracować, ale nie zawsze jest to doświadczenie, które nazwałbym przyjemnym.
I właśnie dlatego zaciekawił mnie Mobilewright.
Bo sama nazwa od razu sugeruje coś w stylu:
„A gdyby tak podejście znane z Playwrighta przenieść do testów aplikacji mobilnych?”
No i brzmi to naprawdę ciekawie.

Czym jest Mobilewright?
Mobilewright to framework do testów end-to-end aplikacji mobilnych na iOS i Androida. Zgodnie z dokumentacją, działa w oparciu o TypeScript API i oferuje między innymi auto-waiting, asercje, raportowanie oraz możliwość uruchamiania testów na symulatorach, emulatorach i realnych urządzeniach.
Czyli w dużym uproszczeniu: zamiast pisać testy mobilne w bardzo ciężkim i mało przyjemnym stylu, dostajemy coś, co ma przypominać doświadczenie znane z Playwrighta.
Nie chodzi oczywiście o to, że Mobilewright magicznie rozwiąże wszystkie problemy testów mobilnych. Mobile zawsze będzie trochę trudniejsze niż web, bo dochodzą urządzenia, systemy operacyjne, uprawnienia, animacje, gesty, instalowanie aplikacji i sporo innych rzeczy.
Ale sam kierunek jest bardzo ciekawy.
Instalacja Mobilewright
Instalacja wygląda dość prosto.
npm install mobilewright @mobilewright/testMożna też zainicjalizować projekt komendą:
npm init mobilewright@latestPo inicjalizacji dostajemy podstawową strukturę projektu, między innymi plik konfiguracyjny mobilewright.config.ts oraz przykładowy test. Dokumentacja pokazuje też uruchamianie testów przez npx mobilewright test oraz raport HTML przez npx mobilewright test --reporter html.
I to jest już pierwsza rzecz, która mi się podoba.
Nie zaczynamy od przekopywania się przez ogromną konfigurację. Dostajemy strukturę podobną do tego, co znamy z nowoczesnych narzędzi frontendowych i testowych.
Przykładowa konfiguracja
Przykładowa konfiguracja może wyglądać mniej więcej tak:
import { defineConfig } from 'mobilewright';
export default defineConfig({
platform: 'ios',
bundleId: 'com.example.myapp',
deviceName: /iPhone 16/,
installApps: './builds/myapp.ipa',
timeout: 10_000,
});W tym przykładzie wskazujemy:
- platformę,
- identyfikator aplikacji,
- urządzenie,
- ścieżkę do aplikacji,
- domyślny timeout.
Nie jest to oczywiście jeszcze cały projekt produkcyjny, ale już widać, że konfiguracja jest czytelna.
I to jest ważne, bo w testach automatycznych bardzo często problemem nie jest samo napisanie jednego testu. Problem zaczyna się wtedy, gdy projekt rośnie, dochodzą kolejne środowiska, kolejne urządzenia, kolejne scenariusze i nagle nikt nie chce dotykać konfiguracji, bo wszystko zaczyna się sypać.
Pierwszy test w Mobilewright
Testy w Mobilewright piszemy w TypeScript, korzystając z test oraz expect z pakietu @mobilewright/test. W dokumentacji pojawia się przykład z fixture screen, który pozwala wyszukiwać elementy i wykonywać na nich akcje.
Prosty test może wyglądać tak:
import { test, expect } from '@mobilewright/test';
test('aplikacja uruchamia się i pokazuje ekran startowy', async ({ screen }) => {
await expect(screen.getByText('Welcome')).toBeVisible();
});I tutaj od razu widać podobieństwo do Playwrighta.
Mamy test, mamy expect, mamy locator, mamy asercję. Nie wygląda to jak kompletnie nowy świat, którego trzeba się uczyć od zera.
Dla osoby, która zna Playwrighta, wejście w taki styl pisania testów może być dużo łatwiejsze niż przechodzenie w klasyczne, bardziej „mobilne” podejście.
Locatory, czyli coś, co może uratować testy mobilne
Jednym z największych problemów w testach UI są selektory.
Na początku każdy myśli:
„Dobra, wezmę jakiś tekst, XPath albo pierwszy lepszy element i będzie działać”.
No i działa.
Przez chwilę.
Potem zmienia się layout, ktoś poprawia UI, dochodzi nowy kontener, element przesuwa się w hierarchii i test zaczyna się wysypywać, mimo że aplikacja działa poprawnie.
Mobilewright pozwala wyszukiwać elementy na kilka sposobów:
screen.getByText('Sign In');
screen.getByLabel('Username');
screen.getByTestId('submit-button');
screen.getByRole('button', { name: 'Submit' });
screen.getByType('TextField');To jest kierunek, który bardzo mi się podoba, bo przypomina podejście znane z Playwrighta i Testing Library.
Czyli zamiast pisać testy oparte o techniczną strukturę ekranu, próbujemy pisać je bardziej z perspektywy użytkownika.
Nie zawsze się da. Nie zawsze aplikacja będzie idealnie przygotowana pod testy. Ale jeżeli mamy wpływ na aplikację, to dodawanie dobrych identyfikatorów, accessibility labeli i sensownych nazw elementów może bardzo mocno poprawić stabilność testów.
Akcje na ekranie
W Mobilewright możemy wykonywać typowe akcje użytkownika, na przykład tapnięcie, dłuższe przytrzymanie, wpisywanie tekstu czy swipe.
Przykład:
import { test, expect } from '@mobilewright/test';
test('użytkownik może zalogować się do aplikacji', async ({ screen }) => {
await screen.getByLabel('Email').fill('user@example.com');
await screen.getByLabel('Password').fill('secret123');
await screen.getByRole('button', { name: 'Sign In' }).tap();
await expect(screen.getByText('Welcome back')).toBeVisible();
});Ten test jest prosty, ale pokazuje najważniejszą rzecz.
Kod jest czytelny.
Nawet osoba, która nie zna dokładnie Mobilewrighta, jest w stanie mniej więcej zrozumieć, co się tutaj dzieje.
Wpisujemy email, wpisujemy hasło, klikamy przycisk, sprawdzamy czy pojawił się tekst powitalny.
I według mnie tak powinny wyglądać dobre testy E2E.
Nie powinny być zagadką. Nie powinny wyglądać jak skrypt napisany tylko dla osoby, która zna każdy szczegół implementacji aplikacji.
Auto-waiting, czyli koniec z losowym czekaniem?
Jedna z rzeczy, które najbardziej psują testy automatyczne, to ręczne czekanie.
Każdy, kto pisał testy UI, zna ten moment:
await sleep(3000);albo:
await page.waitForTimeout(5000);W testach mobilnych pokusa jest jeszcze większa, bo dochodzą animacje, przejścia między ekranami, wolniejsze emulatory i czasami dziwne zachowanie aplikacji.
Problem jest taki, że ręczne czekanie prawie zawsze jest złym rozwiązaniem.
Jeżeli damy za mało czasu, test będzie flaky.
Jeżeli damy za dużo czasu, testy będą wolne.
Jeżeli środowisko raz działa szybciej, a raz wolniej, dalej mamy problem.
Mobilewright, podobnie jak Playwright, stawia na auto-waiting. Asercje takie jak toBeVisible() mają automatycznie czekać, aż warunek zostanie spełniony albo minie timeout.
Przykład:
await expect(screen.getByText('Dashboard')).toBeVisible();I to jest dużo lepsze niż:
await sleep(5000);
await expect(screen.getByText('Dashboard')).toBeVisible();Bo w pierwszym przypadku test czeka na konkretny stan aplikacji.
W drugim przypadku test po prostu czeka, bo mamy nadzieję, że po pięciu sekundach wszystko już będzie gotowe.
A nadzieja to raczej słaba strategia w automatyzacji testów.
Testowanie deep linków
Ciekawie wygląda też fixture device, który pozwala robić rzeczy bardziej związane z samym urządzeniem, a nie tylko z ekranem aplikacji.
Przykład z deep linkiem:
import { test, expect } from '@mobilewright/test';
test('deep link otwiera profil użytkownika', async ({ device, screen }) => {
await device.openUrl('myapp://profile/123');
await expect(screen.getByText('Profile')).toBeVisible();
});To jest praktyczny scenariusz, bo w aplikacjach mobilnych deep linki są bardzo często używane.
Możemy mieć link z maila, powiadomienia push, reklamy, systemu płatności albo zewnętrznej integracji. I warto sprawdzić, czy taki link faktycznie prowadzi użytkownika tam, gdzie powinien.
A co z Appium?
No i tutaj pojawia się naturalne pytanie.
Czy Mobilewright zastąpi Appium?
Moim zdaniem to nie jest dobre pytanie na tym etapie.
Appium jest dojrzałym, znanym i szeroko używanym narzędziem. Ma ogromny ekosystem, dużo materiałów, dużo przykładów i sporo firm już z niego korzysta.
Mobilewright wygląda raczej jak bardzo ciekawa alternatywa dla osób, które lubią styl Playwrighta i chciałyby pisać testy mobilne w podobny sposób.
Ja bym nie podchodził do tego tak:
„Od jutra wyrzucamy Appium i przepisujemy wszystko na Mobilewright”.
Bardziej:
„Sprawdźmy, czy Mobilewright może uprościć testowanie aplikacji mobilnych, szczególnie w nowych projektach albo mniejszych proof of concept”.
To jest zdrowsze podejście.
Nowe narzędzia potrafią być świetne, ale trzeba patrzeć na nie rozsądnie. Liczy się nie tylko ładne API, ale też stabilność, dokumentacja, community, integracja z CI/CD, wsparcie dla różnych urządzeń i zachowanie w większym projekcie.
Kiedy Mobilewright może mieć sens?
Moim zdaniem Mobilewright może być ciekawy szczególnie wtedy, gdy:
masz zespół, który zna już Playwrighta,
piszesz testy w TypeScript,
chcesz przetestować aplikację mobilną bez wchodzenia od razu w ciężki setup,
budujesz nowy projekt i możesz dobrać narzędzie od początku,
chcesz zrobić proof of concept automatyzacji mobilnej,
zależy Ci na czytelnym API i testach podobnych do testów webowych.
Największy potencjał widzę tutaj w zespołach, które mają już doświadczenie z Playwrightem. Wtedy mentalny przeskok może być dużo mniejszy.
Kiedy byłbym ostrożny?
Nie wrzucałbym Mobilewrighta od razu do każdego projektu.
Byłbym ostrożny, jeżeli:
masz ogromną istniejącą bazę testów w Appium,
projekt działa na wielu nietypowych urządzeniach,
masz bardzo specyficzne wymagania enterprise,
potrzebujesz narzędzia maksymalnie sprawdzonego przez lata,
nie masz czasu na eksperymenty i analizę ryzyka.
To nie jest minus Mobilewrighta. To po prostu normalne podejście do każdego nowego narzędzia.
Nowe frameworki często wyglądają świetnie na pierwszym przykładzie. Prawdziwy test zaczyna się dopiero wtedy, gdy mamy kilkadziesiąt albo kilkaset testów, kilka środowisk, CI/CD, równoległe uruchamianie i realne błędy aplikacji.
Przykładowy scenariusz testowy
Załóżmy, że mamy prostą aplikację mobilną z logowaniem.
Chcemy sprawdzić:
- czy formularz logowania jest widoczny,
- czy użytkownik może wpisać dane,
- czy po kliknięciu przycisku trafia na ekran główny.
Przykładowy test:
import { test, expect } from '@mobilewright/test';
test.describe('Login', () => {
test('użytkownik może zalogować się poprawnymi danymi', async ({ screen }) => {
await expect(screen.getByLabel('Email')).toBeVisible();
await expect(screen.getByLabel('Password')).toBeVisible();
await screen.getByLabel('Email').fill('user@example.com');
await screen.getByLabel('Password').fill('secret123');
await screen.getByRole('button', { name: 'Sign In' }).tap();
await expect(screen.getByText('Dashboard')).toBeVisible();
});
test('użytkownik widzi błąd po wpisaniu złych danych', async ({ screen }) => {
await screen.getByLabel('Email').fill('wrong@example.com');
await screen.getByLabel('Password').fill('wrong-password');
await screen.getByRole('button', { name: 'Sign In' }).tap();
await expect(screen.getByText('Invalid credentials')).toBeVisible();
});
});I znowu — to wygląda normalnie.
Nie trzeba tłumaczyć przez 20 minut, co robi każda linia. Test jest blisko języka użytkownika.
Dla mnie to jest ogromna zaleta.
Co mi się podoba w Mobilewright?
Najbardziej podoba mi się sama filozofia.
Czytelne testy.
TypeScript.
Locatory podobne do Playwrighta.
Auto-waiting.
Asercje.
Raporty.
Obsługa iOS i Androida.
To wszystko brzmi jak coś, czego w testach mobilnych od dawna brakuje w bardziej przystępnej formie.
Oczywiście nie twierdzę, że Mobilewright jest idealny albo że za chwilę wszyscy będą go używać. Na takie wnioski jest za wcześnie.
Ale jako kierunek rozwoju automatyzacji mobilnej — wygląda to bardzo obiecująco.
Podsumowanie
Mobilewright to narzędzie, które zdecydowanie warto obserwować.
Szczególnie jeśli znasz Playwrighta i lubisz jego styl pisania testów, Mobilewright może być dla Ciebie bardzo ciekawym wejściem w świat automatyzacji aplikacji mobilnych.
Nie traktowałbym go jeszcze jako oczywistego zamiennika dla Appium w każdym projekcie. Bardziej jako nowe, świeże podejście, które może uprościć pisanie testów mobilnych i sprawić, że będą one bardziej czytelne.
A to jest naprawdę ważne.
Bo dobre testy automatyczne to nie tylko testy, które „jakoś działają”.
Dobre testy to takie, które da się utrzymać, zrozumieć, rozwijać i uruchamiać bez ciągłej walki ze środowiskiem.
I jeżeli Mobilewright pójdzie w tym kierunku, to może być naprawdę ciekawe narzędzie dla testerów, QA automation engineerów i zespołów, które chcą podejść do testów mobilnych trochę nowocześniej.


