E2E Testing Mobile (Detox) — Mobile

End-to-End Testing di Mobile E2E testing di mobile lebih kompleks dari web karena perlu berinteraksi dengan native UI, permissions, gestures, dan…

E2E (end-to-end) test adalah robot yang memakai aplikasi sungguhan di simulator atau emulator, persis seperti pengguna: membuka aplikasi, mengetuk, lalu membaca layar. Bayangin uji coba sebelum cabang baru Bu Rini buka. Memeriksa mesin cuci satu per satu itu test unit. Menyuruh seorang karyawan berpura-pura jadi pelanggan, dari datang membawa cucian sampai menerima nota, itu test E2E.

🧪 Tebakan cepat: Daftar pesanan datang dari server dalam 2 detik. Test Detox-mu langsung menjalankan await expect(element(by.id('order-13'))).toBeVisible() setelah aplikasi terbuka, tanpa sleep. Lulus atau gagal? Jawabannya ada di bagian "Detox: gray-box dan sinkronisasi".

Piramida test untuk aplikasi ini

Lapisan Yang diuji Alat Jumlah
Unit fungsi biasa: rupiah(14000) jadi 'Rp 14.000' Jest banyak
Komponen OrderRow menampilkan #13 dan meneruskan ketukan Jest + React Native Testing Library cukup banyak
E2E buka aplikasi → lihat order #13 → buka detailnya Maestro atau Detox sedikit, alur penting saja

Test unit dan komponen jalan dalam hitungan detik di laptop. Test E2E butuh build aplikasi dan simulator, jadi lambat dan lebih rapuh: pakai untuk alur yang kalau rusak bikin rugi (login, lihat order, minta jemput). Versi per 11 Oktober 2026: jest-expo 57.0.5 (di atas Jest 29.7), @testing-library/react-native 14.1.0, Maestro CLI 2.11.0, Detox 20.51.4.

Test komponen: Jest dan React Native Testing Library

npx expo install jest-expo jest @types/jest --dev
npx expo install @testing-library/react-native --dev
npm install -D [email protected]   # RNTL 14 butuh test-renderer, versi 1.2 untuk React 19.2

Di package.json: "jest": { "preset": "jest-expo" } dan skrip "test": "jest --watchAll". OrderRow dipindah ke src/components/OrderRow.tsx dan diberi testID:

// src/components/__tests__/OrderRow.test.tsx
import { render, screen, userEvent } from '@testing-library/react-native';
import { OrderRow } from '@/components/OrderRow';
import type { Order } from '@/data/orders';

const order13: Order = { id: '13', nama: 'Mbak Wulan', kg: 2, status: 'Disetrika' };

test('OrderRow menampilkan order #13 dan mengirim id-nya saat diketuk', async () => {
  const onPress = jest.fn();
  const user = userEvent.setup();
  await render(<OrderRow order={order13} onPress={onPress} />);

  expect(screen.getByText('#13 Mbak Wulan')).toBeOnTheScreen();
  expect(screen.getByText('2 kg · Rp 14.000')).toBeOnTheScreen();
  expect(screen.getByText('Disetrika')).toBeOnTheScreen();

  await user.press(screen.getByTestId('order-13'));
  expect(onPress).toHaveBeenCalledWith('13');
});

Dijalankan di project ini:

$ npx jest src/components/__tests__/OrderRow.test.tsx
PASS src/components/__tests__/OrderRow.test.tsx
  ✓ OrderRow menampilkan order #13 dan mengirim id-nya saat diketuk (460 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total

testID: pegangan untuk robot

<Pressable testID={`order-${order.id}`} onPress={() => onPress(order.id)}>

testID jadi accessibility identifier di iOS dan pengenal view di Android. Jest, Maestro (id:), dan Detox (by.id) mencari lewat situ. Mencari lewat teks juga bisa, tapi gampang patah: teksnya diterjemahkan atau diganti sedikit, test-nya gagal.

Maestro: alur dalam YAML

Maestro adalah CLI terpisah (butuh Java 17+), dipasang dengan curl -fsSL "https://get.maestro.mobile.dev" | bash. Aplikasinya gak perlu diubah sama sekali:

# .maestro/buka-order-13.yaml
appId: id.laundryburini.app
---
- launchApp:
    clearState: true
- assertVisible:
    id: "order-13"
- tapOn:
    id: "order-13"
- assertVisible: "Mbak Wulan: Disetrika"

Detox: gray-box dan sinkronisasi

Detox (dari Wix) menulis test dalam JavaScript dengan runner Jest 29, dan library-nya ikut masuk ke aplikasi. Karena "melihat ke dalam" aplikasi, Detox disebut gray-box:

// e2e/order.test.js
describe('Pesanan saya', () => {
  beforeAll(async () => {
    await device.launchApp({ newInstance: true });
  });

  it('membuka detail order #13', async () => {
    await expect(element(by.id('order-13'))).toBeVisible();
    await element(by.id('order-13')).tap();
    await expect(element(by.text('Mbak Wulan: Disetrika'))).toBeVisible();
  });
});
Maestro Detox
Bahasa test YAML JavaScript (Jest)
Menunggu mencoba ulang sampai 7 detik per pemeriksaan menunggu aplikasi diam (gray-box)
Perubahan di aplikasi gak ada library Detox ikut di-build, plus config plugin di Expo
Expo Go lewat openLink gak bisa, butuh build sendiri

Test yang kadang lulus kadang gagal (flaky)

⚠️ Jebakan yang sering ketemu

TL;DR: Piramida test Laundry Bu Rini: banyak test unit dan komponen dengan Jest (jest-expo 57.0.5, Jest 29.7) dan React Native Testing Library 14.1.0 (await render, userEvent.press, getByTestId), dan sedikit test E2E untuk alur "buka aplikasi → order #13 → detail". testID (order-13 untuk order #13) adalah pegangan untuk semua alat. Maestro (CLI 2.11.0) menulis alur dalam YAML (launchApp, assertVisible, tapOn dengan id), gak mengubah aplikasi, dan mencoba ulang tiap pemeriksaan sampai 7 detik; Expo merekomendasikannya untuk EAS Workflows. Detox (20.51.4) adalah framework E2E untuk React Native yang menjalankan test di simulator atau emulator sungguhan, ditulis dalam JavaScript, dengan sinkronisasi otomatis gray-box: dia menunggu jaringan, timer, animasi, dan thread JavaScript sendiri, dan untuk kasus khusus memakai waitFor().toBeVisible().withTimeout(). Test jadi flaky karena data yang berubah, sleep, dialog izin, dan sisa state: pakai data tetap, menunggu yang benar, dan mulai bersih.

Yang akan kamu pelajari