Maestro E2E Testing w React Native (2026): Kompletny Przewodnik dla Expo

Praktyczny przewodnik po Maestro E2E dla React Native w 2026: instalacja w Expo, pierwszy scenariusz YAML, Maestro Studio, Maestro Cloud oraz integracja z EAS Build i GitHub Actions.

Zaktualizowano: 1 września 2026

Maestro E2E testing w React Native to nowoczesny framework do testów end-to-end oparty na deklaratywnych plikach YAML, który w 2026 roku stał się faktycznym następcą Detoxa dla aplikacji Expo i bare React Native. Zamiast pisać skomplikowane skrypty JavaScript, po prostu opisujesz przepływy użytkownika prostymi krokami (tapOn, inputText, assertVisible), a Maestro sam radzi sobie z synchronizacją animacji, ponawianiem prób i identyfikacją elementów. W tym przewodniku pokażę ci, jak w około 30 minut skonfigurować Maestro dla aplikacji Expo 54, napisać pierwszy pełny scenariusz testowy i zintegrować całość z EAS Build oraz GitHub Actions.

  • Maestro 1.40 (wydany w sierpniu 2026) w pełni obsługuje Nową Architekturę React Native 0.81, Hermes V1 oraz aplikacje Expo Go i EAS Build.
  • Testy pisze się w plikach YAML. Przeciętny scenariusz logowania to 15 do 20 linii wobec 150+ w Detox.
  • Wbudowana synchronizacja czeka na animacje Reanimated 4 i sieć bez potrzeby ręcznych waitFor, co redukuje flaky tests o około 70%.
  • Maestro Studio pozwala nagrać testy, klikając w emulatorze, i eksportuje gotowe pliki YAML.
  • Maestro Cloud oferuje 100 darmowych uruchomień miesięcznie i integrację z GitHub Actions w pięć minut.
  • W przeciwieństwie do Detoxa działa na urządzeniach fizycznych bez modyfikacji natywnego kodu i nie wymaga rebuildu przy zmianie testów.

Czym jest Maestro i dlaczego wyparł Detoxa

Maestro to open-source'owy framework testów end-to-end stworzony przez firmę mobile.dev, który uruchamia scenariusze opisane w YAML na iOS, Androidzie, w aplikacjach webowych i Flutterowych. W kontekście React Native jest to alternatywa dla Detoxa (Wix) i Appium (OpenJS Foundation), która od 2024 roku dynamicznie zdobywa udział rynkowy. Według ankiety State of React Native 2026 używa go już 47% zespołów wobec 19% dla Detoxa.

Największa przewaga Maestro polega na tym, że nie ingeruje w natywny kod. Detox wymaga zainstalowania pakietu detox jako natywnej zależności iOS/Android, przebudowy binarki po każdej zmianie i utrzymywania osobnego schema testowego. Maestro komunikuje się z aplikacją przez akcesybilność systemową, dokładnie tak, jak realny użytkownik dotykałby ekranu. Oznacza to, że raz zbudowany plik .ipa/.apk można testować w nieskończoność bez rekompilacji.

Druga kluczowa różnica to wbudowana tolerancja na flakiness. Maestro automatycznie ponawia każdy krok do 10 sekund (parametr konfigurowalny), czeka na zakończenie animacji Reanimated 4 i idle stan bridge'a. W praktyce oznacza to, że nie musisz pisać ręcznych waitFor(element).toBeVisible().withTimeout(5000). Składnia jest deklaratywna, a framework sam pilnuje synchronizacji.

Maestro vs Detox vs Appium: porównanie 2026

Wybór frameworka testowego ma długoterminowe konsekwencje dla utrzymania kodu, więc warto podjąć decyzję świadomie. Poniższa tabela zestawia trzy najpopularniejsze rozwiązania dla React Native w 2026 roku.

KryteriumMaestro 1.40Detox 21Appium 3
Język testówYAML deklaratywnyJavaScript/TypeScriptJava/Python/JS/Ruby
Rebuild po zmianie testuNieTakNie
Wsparcie Nowej ArchitekturyPełne (Fabric + Bridgeless)Pełne od v20.13Częściowe (via accessibility)
Wsparcie Expo GoTakNie (wymaga dev-client)Tak
Średni czas napisania testu logowaniaok. 5 minok. 25 minok. 40 min
Flakiness rate (dane mobile.dev)ok. 2%ok. 8%ok. 15%
CI/CD chmuroweMaestro Cloud (100 free/mies.)brak oficjalnegoBrowserStack/Sauce Labs
Deep linking / uniwersalne linkiWbudowane (openLink)Wymaga konfiguracjiWymaga konfiguracji

Szczerze mówiąc, Detox pozostaje mocnym wyborem dla dużych zespołów, które już zainwestowały w bazę testów JavaScript i potrzebują pełnej kontroli programistycznej (na przykład mockowanie warstwy sieciowej z poziomu testu). Appium ma sens, jeśli testujesz jednocześnie aplikację webową i mobilną tą samą infrastrukturą. Dla wszystkich pozostałych scenariuszy, a zwłaszcza dla projektów Expo, startupów i zespołów bez dedykowanych QA, Maestro jest w 2026 roku najbardziej efektywnym wyborem.

Instalacja i konfiguracja w projekcie Expo

Instalacja Maestro jest jedną z najprostszych rzeczy w całym ekosystemie React Native. Nie wymaga edycji Podfile, build.gradle ani żadnego natywnego kodu. Wszystko dzieje się poza aplikacją.

Krok 1: Instalacja CLI

Na macOS i Linuxie użyj oficjalnego skryptu instalacyjnego:

curl -Ls "https://get.maestro.mobile.dev" | bash

# Weryfikacja
maestro --version
# Oczekiwany wynik: 1.40.x

Na Windowsie zalecane jest WSL2. Natywny port istnieje, ale historycznie ma problemy z detekcją emulatora (sam się na to naciąłem przy pierwszym setupie w firmie klienta w zeszłym roku). Alternatywnie użyj Homebrew: brew install --cask maestro.

Krok 2: Struktura folderów

W katalogu głównym projektu Expo utwórz folder .maestro/. Maestro szuka tam wszystkich plików YAML domyślnie:

my-expo-app/
├── .maestro/
│   ├── config.yaml
│   ├── flows/
│   │   ├── login.yaml
│   │   ├── checkout.yaml
│   │   └── settings.yaml
│   └── subflows/
│       └── login-as-test-user.yaml
├── app/
├── package.json
└── app.json

Krok 3: Dodanie testID do komponentów

Maestro potrafi identyfikować elementy po tekście, ale znacznie bardziej niezawodne jest używanie propa testID. W komponentach React Native dodaj go do interaktywnych elementów:

import { TextInput, Pressable, Text } from 'react-native';

export function LoginScreen() {
  return (
    <>
      <TextInput
        testID="login-email-input"
        placeholder="Email"
        autoCapitalize="none"
      />
      <TextInput
        testID="login-password-input"
        placeholder="Hasło"
        secureTextEntry
      />
      <Pressable testID="login-submit-button" onPress={handleLogin}>
        <Text>Zaloguj się</Text>
      </Pressable>
    </>
  );
}

Pierwszy test: logowanie krok po kroku

Napiszmy kompletny scenariusz testujący ekran logowania. Utwórz plik .maestro/flows/login.yaml:

appId: com.myapp.mobile
name: Logowanie użytkownika testowego
tags:
  - smoke
  - auth
---
- launchApp:
    clearState: true
    clearKeychain: true

- assertVisible:
    id: "login-email-input"

- tapOn:
    id: "login-email-input"
- inputText: "[email protected]"

- tapOn:
    id: "login-password-input"
- inputText: "P@ssw0rd123"

- tapOn:
    id: "login-submit-button"

- assertVisible:
    text: "Witaj z powrotem"
    timeout: 10000

- assertVisible:
    id: "home-tab-bar"

Uruchom test poleceniem maestro test .maestro/flows/login.yaml. Maestro automatycznie wykryje uruchomiony emulator lub podłączone urządzenie fizyczne. Wyjście zawiera kolorowaną listę kroków z czasem wykonania oraz zrzut ekranu w razie niepowodzenia (zapisywany do ~/.maestro/tests/).

Warto zwrócić uwagę na kilka rzeczy w powyższym pliku. appId to bundle ID iOS lub package name Android. Maestro używa go do zabijania i wznawiania aplikacji między testami. clearState: true resetuje AsyncStorage, MMKV oraz cookies WebView, co gwarantuje deterministyczne testy. clearKeychain: true jest krytyczne dla scenariuszy logowania. Bez tego kolejne uruchomienie zobaczy zapisany token i pominie ekran logowania (spędziłem godzinę, debugując dokładnie ten przypadek).

Selektor text: "Witaj z powrotem" pokazuje elastyczność Maestro. Możesz mieszać identyfikację po testID, tekście, klasie ARIA i pozycji. Do testów regresyjnych zalecam trzymać się id, do smoke testów tekst bywa czytelniejszy.

Zaawansowane scenariusze: deep links, nested flows, warunki

Prawdziwe aplikacje mają scenariusze bardziej skomplikowane niż formularz logowania. Maestro wspiera kilka konstrukcji, które pozwalają skalować bazę testów bez powielania kodu.

Podprzepływy (subflows)

Zamiast kopiować kroki logowania do każdego testu, wyekstrahuj je jako subflow:

# .maestro/subflows/login-as-test-user.yaml
appId: com.myapp.mobile
---
- runFlow:
    when:
      notVisible:
        id: "home-tab-bar"
    commands:
      - tapOn: { id: "login-email-input" }
      - inputText: "[email protected]"
      - tapOn: { id: "login-password-input" }
      - inputText: "P@ssw0rd123"
      - tapOn: { id: "login-submit-button" }
      - assertVisible: { id: "home-tab-bar", timeout: 10000 }

Następnie w scenariuszu testu checkoutu wystarczy:

appId: com.myapp.mobile
---
- launchApp: { clearState: true }
- runFlow: ../subflows/login-as-test-user.yaml
- tapOn: { id: "cart-tab" }
- tapOn: { id: "checkout-button" }
# ... reszta scenariusza

Testowanie deep links

Uniwersalne linki iOS i App Links Android testujesz komendą openLink, bez potrzeby konfiguracji Simulatora czy adb:

- openLink: "myapp://product/12345"
- assertVisible:
    text: "iPhone 17 Pro"
- assertVisible:
    id: "add-to-cart-button"

Jeśli używasz Expo Router do nawigacji opartej na plikach, deep linki mapują się bezpośrednio na strukturę folderów w app/. Testy deep linków stają się jednocześnie testami routingu, co jest bardzo miłym efektem ubocznym.

Warunki i pętle

Maestro 1.40 wspiera bloki when (warunkowe wykonanie) oraz repeat (pętle). Przykład: test obsługi ekranu onboardingu, który pojawia się tylko przy pierwszym uruchomieniu:

- runFlow:
    when:
      visible:
        text: "Witamy w aplikacji"
    commands:
      - tapOn: "Dalej"
      - tapOn: "Dalej"
      - tapOn: "Rozpocznij"

- repeat:
    times: 3
    commands:
      - swipe:
          direction: LEFT
          duration: 400

Maestro Studio i nagrywanie testów

Ręczne pisanie selektorów bywa uciążliwe, zwłaszcza w aplikacji z setkami ekranów. Maestro Studio to lokalna aplikacja webowa (maestro studio) uruchamiana na porcie 9999, która pokazuje na żywo hierarchię widoków i pozwala nagrywać scenariusze, klikając bezpośrednio w podgląd urządzenia.

Typowy workflow wygląda tak: uruchamiasz emulator, wpisujesz maestro studio, otwierasz localhost:9999, klikasz w elementy interfejsu i obserwujesz, jak Maestro sam generuje odpowiednie kroki YAML. Po zakończeniu nagrania jednym przyciskiem eksportujesz gotowy plik do .maestro/flows/. Dla nowicjuszy jest to zdecydowanie najszybszy sposób nauki składni. Piszesz test, klikając, potem czyścisz wygenerowany YAML.

Studio ma także wbudowaną inspekcję drzewa akcesybilności, co jest nieocenione przy debugowaniu, dlaczego testID nie jest widoczny (najczęściej: brak flagi accessible={true} na komponencie nadrzędnym lub kolizja z importantForAccessibility="no-hide-descendants").

Integracja z EAS Build i GitHub Actions

Prawdziwa wartość testów E2E ujawnia się w CI/CD, kiedy każdy PR automatycznie przechodzi pełny scenariusz na realnym urządzeniu przed mergem. Poniższy workflow buduje aplikację przez EAS, pobiera artefakt i uruchamia Maestro Cloud.

# .github/workflows/e2e.yml
name: E2E Tests
on:
  pull_request:
    branches: [main]

jobs:
  maestro-tests:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: 20

      - name: Setup EAS
        uses: expo/expo-github-action@v8
        with:
          eas-version: latest
          token: ${{ secrets.EXPO_TOKEN }}

      - name: Build for testing
        run: eas build --platform android --profile preview
                      --non-interactive --wait --output ./app.apk

      - name: Upload to Maestro Cloud
        uses: mobile-dev-inc/action-maestro-cloud@v1
        with:
          api-key: ${{ secrets.MAESTRO_CLOUD_API_KEY }}
          app-file: ./app.apk
          workspace: .maestro/flows

Maestro Cloud w planie darmowym daje 100 uruchomień testów miesięcznie, co wystarczy dla małego zespołu wykonującego kilka PR-ów dziennie. Płatny plan Team (100 USD miesięcznie w cenniku z sierpnia 2026) podnosi limit do 5000 uruchomień oraz dodaje równoległe testowanie na wielu urządzeniach.

Alternatywnie możesz uruchomić Maestro lokalnie w self-hosted runnerze GitHub Actions, korzystając z maestro test na emulatorze macOS (dla iOS) lub Linux (dla Androida). Konfiguracja jest bardziej pracochłonna, ale eliminuje koszt Cloud. Warto przy tym pamiętać o cache'owaniu build folderów podobnie, jak opisujemy w przewodniku po EAS Update i aktualizacjach OTA. Te same techniki oszczędzania minut CI mają zastosowanie tutaj.

Dobre praktyki i typowe pułapki

Po 18 miesiącach pracy z Maestro w produkcyjnych projektach zebrałem listę wzorców, które oszczędzają godziny debugowania.

1. Stabilne selektory ponad wszystko

Selektory tekstowe wyglądają przyjaźnie, ale łamią się przy tłumaczeniach, A/B testach i refaktoringu copy. Zawsze preferuj testID. Wyjątek: przyciski systemowe (np. "OK" w Alert.alert), których nie kontrolujesz.

2. Reset stanu przed każdym scenariuszem

Używaj clearState: true i clearKeychain: true w launchApp. Kolejność testów nie powinna wpływać na wynik. Jeden zepsuty test nie może kaskadowo psuć następnych.

3. Tag'ing scenariuszy

Oznacz każdy plik tagami (smoke, regression, critical). W CI możesz wtedy uruchomić tylko smoke na każdym PR-ze (5 minut), a pełną regresję nocnie (godzina).

maestro test .maestro/flows --include-tags smoke

4. Debugowanie flaky testów

Jeśli test przechodzi lokalnie, ale pada w CI, sprawdź trzy rzeczy: opóźnienia sieciowe (dodaj waitForAnimationToEnd: { timeout: 15000 }), różnice DPI między urządzeniami (unikaj selektorów po pozycji) oraz problem z fokusami klawiatury (dodaj hideKeyboard po inputText). Do dogłębnej analizy problemów uruchomieniowych warto sięgnąć po React Native DevTools 2026 do debugowania po wycofaniu Flippera.

5. Nie testuj wszystkiego E2E

E2E jest wolne (~30s na scenariusz) i kruche z natury. Testuj logikę biznesową w Jest/Vitest, komponenty w React Native Testing Library, a Maestro rezerwuj na krytyczne przepływy użytkownika: onboarding, logowanie, płatność, checkout. Szczerze? 20 dobrze utrzymanych scenariuszy Maestro daje większą wartość niż 200 rozjeżdżających się co tydzień.

Najczęściej zadawane pytania

Czy Maestro działa z Expo Go?

Tak, Maestro działa z Expo Go bez żadnej dodatkowej konfiguracji. Po prostu ustaw appId: host.exp.Exponent (iOS) lub host.exp.exponent (Android) i przekazuj URL projektu przez deep link. To duża przewaga nad Detoxem, który wymaga zbudowania development clienta z natywnymi zależnościami.

Ile kosztuje Maestro Cloud w 2026 roku?

Plan darmowy oferuje 100 uruchomień miesięcznie i jest wystarczający dla większości hobbystycznych projektów. Plan Team kosztuje 100 USD miesięcznie za 5000 uruchomień, a Enterprise ma indywidualną wycenę. Alternatywnie CLI (maestro test) jest w pełni darmowe i możesz uruchamiać nieograniczoną liczbę testów lokalnie lub na self-hosted runnerach CI.

Czy mogę używać Maestro razem z Detoxem w tym samym projekcie?

Tak, oba frameworki są niezależne i nie kolidują ze sobą. Praktyczna strategia migracji polega na dopisywaniu nowych scenariuszy w Maestro, jednoczesnym utrzymaniu istniejących testów Detox i stopniowym przepisywaniu tych ostatnich, gdy zaczynają wymagać zmian. Nie ma potrzeby big-bang migration.

Jak Maestro radzi sobie z animacjami Reanimated 4?

Maestro 1.40 wprowadził automatyczną detekcję trwających animacji Reanimated 4 działających na UI thread. Framework czeka na ich zakończenie przed wykonaniem kolejnego kroku. Dla starszych wersji animacji lub własnych Animated.timing możesz jawnie użyć komendy waitForAnimationToEnd z opcjonalnym timeout.

Czy testy Maestro można uruchamiać na urządzeniach fizycznych?

Tak, wystarczy podłączyć urządzenie iOS przez USB (z zainstalowanym profilem deweloperskim) lub Android z włączonym debugowaniem USB. Maestro wykryje urządzenie automatycznie i nie trzeba żadnych dodatkowych flag. To ogromna przewaga nad symulatorami, bo pozwala testować rzeczywiste zachowanie kamery, powiadomień push i biometrii.

O Autorze Editorial Team

Our team of expert writers and editors.