Lompat ke konten utama

React Native Testing Library: Cara Test Aplikasi dengan Benar

Kuasai React Native Testing Library dengan tips setup, query, mocking, dan CI. Bangun test andal yang user-centric untuk komponen, hooks, dan navigasi.

React Native Testing Library: Cara Test Aplikasi dengan Benar

Test suite React Native Anda sudah hijau, tapi user tetap melapor bahwa tap “Continue” tidak melakukan apa pun di perangkat nyata. Test komponen menemukan tombolnya, memanggil handler-nya, dan melihat layar yang diharapkan di lingkungan JavaScript yang di-mock. Tapi test itu tidak pernah memverifikasi prompt izin native, perilaku keyboard, animasi, API platform, atau stack navigasi yang sebenarnya.

Celah itulah yang bikin tim punya kepercayaan diri palsu. React Native Testing Library sangat bagus untuk mengetes apa yang dirender komponen dan bagaimana ia merespons interaksi user, tapi bukan pengganti device testing atau pengukuran performa. Strategi yang andal adalah memakai tiap layer untuk kegagalan yang bisa ditangkapnya.

Table of Contents

Mengapa User Centric Testing Mengubah Segalanya

Kegagalan tes umum sering terjadi sebelum tes ditulis. Developer memeriksa props komponen, mengakses state, atau membandingkan snapshot besar karena detail tersebut mudah di-assert. Tes berhasil, lalu refactor mengubah struktur komponen tanpa mengubah pengalaman pengguna, dan suite pun error. Lebih buruk lagi, tes bisa tetap berhasil padahal perilaku yang terlihat oleh user salah karena asersi tidak pernah mendeskripsikan apa yang perlu dilihat user.

React Native Testing Library mengambil pendekatan sebaliknya. Anda me-render komponen, berinteraksi melalui kontrol yang terlihat, lalu melakukan asersi pada hasil yang bisa diobservasi user. Pendekatan tersebut sesuai dengan contoh berpusat pada user dari React Native Testing Library, serta panduan testing React Native untuk menjaga tes tetap singkat, fokus pada satu hal, memisahkan urusan view dari business logic dan state, serta lebih mengutamakan output visual atau accessibility helpers daripada detail implementasi internal.

Diagram yang mengilustrasikan manfaat user-centric testing, menyoroti perilaku user, resiliensi, reliabilitas, dan praktik terbaik.

Tes perilaku yang diandalkan user

Misalkan form login menonaktifkan tombol submit saat request berjalan. Tes yang rapuh mungkin memeriksa disabled pada instance komponen tertentu atau memastikan variabel state berubah. Test yang lebih kuat akan menekan kontrol “Sign in”, menunggu indikator loading, lalu mengecek apakah pesan error atau layar tujuan muncul.

Test kedua tidak peduli apakah form tersebut menggunakan local state, reducer, custom hook, atau implementasi button yang berbeda. Yang penting adalah aplikasi memberikan hasil yang benar.

Aturan praktis: Jika user tidak bisa mengobservasinya, pertanyakan apakah hal tersebut layak masuk ke dalam test perilaku komponen.

Query berdasarkan accessibility label dan role juga mendorong code produk yang lebih baik. Layar dengan label yang bermakna lebih mudah digunakan dengan assistive technology dan lebih mudah diuji. Koneksi ini penting saat Anda menilai pengalaman pengguna aplikasi, karena testability dan usability sering kali meningkat secara bersamaan.

Know what passing tests don’t prove

Component test yang berpusat pada user dapat membuktikan bahwa JavaScript merender branch yang diharapkan dan merespons simulasi tekanan. Namun, ia tidak bisa membuktikan apakah prompt biometrik terbuka dengan benar, apakah kamera native mengembalikan hasil yang bisa digunakan, atau apakah alur pembayaran tetap aman saat menghadapi lifecycle spesifik platform.

Batasan tersebut bukanlah kelemahan library ini. Itu adalah alasan untuk menjaga integritas tiap layer test. Gunakan RNTL untuk perilaku komponen, lalu simpan device-based tests untuk alur di mana integrasi native, navigasi real, permission, autentikasi, pembayaran, atau fungsi inti aplikasi dapat mengubah hasil akhirnya.

Instalasi dan Konfigurasi yang Benar-benar Berhasil

Setup modern dimulai dengan scoped package:

@testing-library/react-native

Versi lama react-native-testing-library nama package npm masih ada sebagai arsip sejarah, tetapi proyek saat ini sebaiknya menggunakan scoped package yang dikelola dalam keluarga Testing Library. Proyek ini repositori GitHub mendeskripsikannya sebagai utilitas React Native untuk mendorong praktik testing yang baik, dan riwayat rilisnya menunjukkan bahwa library ini terus berkembang seiring React Native, bukan sekadar helper statis.

Instal library ini dengan environment Jest Anda yang sudah ada. Proyek Expo biasanya menggunakan preset Expo Jest, sedangkan proyek bare React Native mungkin menggunakan preset React Native:

npm install --save-dev @testing-library/react-native jest

Untuk Expo, tambahkan preset yang sudah digunakan proyek Anda:

{
  "scripts": {
    "test": "jest"
  },
  "jest": {
    "preset": "jest-expo"
  }
}

Untuk aplikasi bare React Native, gunakan konfigurasi React Native Jest yang sesuai. Pastikan preset selaras dengan versi framework. Banyak error yang terlihat seperti masalah RNTL sebenarnya berasal dari ketidakcocokan React renderer, Babel transform, atau preset Jest.

Buat file setup yang eksplisit

Letakkan konfigurasi environment bersama di file setup daripada mengulang mock di setiap test:

// jest.setup.js
import '@testing-library/react-native/extend-expect';

Lalu referensikan dari Jest:

{
  "jest": {
    "preset": "jest-expo",
    "setupFilesAfterEnv": ["<rootDir>/jest.setup.js"]
  }
}

Jika aplikasi Anda menggunakan React Navigation, Reanimated, gesture handling, safe-area context, atau modul storage, cukup konfigurasi mock yang dibutuhkan environment test Anda. Global mock yang mengubah perilaku aplikasi bisa membuat semua test mudah lolos, tapi membuat seluruh suite jadi kurang terpercaya.

TypeScript juga butuh perhatian serupa. Pastikan Jest melakukan transform pada .ts dan .tsx file melalui preset atau konfigurasi Babel Anda, dan pastikan tipe test tetap tersedia bagi compiler. Test yang jalan di lokal tapi tidak di-type-check bisa menyembunyikan nama query yang salah, parameter navigasi tidak valid, atau bentuk mock yang tidak aman.

Kronologi rilis sangat berguna saat mendiagnosis saran setup lama. Proyek ini mencatat 127 rilis, dengan v14.0.1 ditandai pada 2026-06-23, sementara v12.9.0, yang dirilis pada 2024-11-27, menambahkan dukungan resmi untuk React Native 0.77 dan Expo 52. Versi v14 alpha pada Maret 2025 beralih ke Universal Test Renderer dari React Test Renderer yang sudah deprecated dan bersiap untuk dukungan khusus React 19. Detail ini dapat dilihat di riwayat rilis RNTL, jadi jangan asal copy dependency renderer dari tutorial lama tanpa cek versi app Anda.

Untuk dasar Jest yang praktis, bandingkan konfigurasi Anda dengan panduan unit test JavaScript ini, lalu jalankan satu test komponen kecil sebelum menambah navigation dan native mocks.

Infografis yang menunjukkan lima langkah instalasi untuk setup proyek React Native Testing Library.

Penjelasan Core API Queries dan Assertions

Test RNTL jadi terpercaya saat query-nya sesuai dengan apa yang bisa dilihat, ditemukan, dan dioperasikan user. API memang kecil, tapi memilih selector yang mengekspos detail implementasi bisa membuat test yang lolos jadi menyesatkan.

Mulai dengan render:

const screen = render(<LoginForm />);

Pilih query yang paling relevan bagi user. Utamakan query berbasis accessibility jika komponen menyediakannya, gunakan visible text jika teks adalah perilakunya, dan sisakan testID untuk kasus tanpa selector user-facing yang bermakna atau saat butuh integration hook yang stabil.

Infografis grafik piramida yang menunjukkan urutan prioritas query yang direkomendasikan untuk otomatisasi software testing.

Pilih query berdasarkan timing dan intent

Setiap jenis query memiliki kegunaan berbeda:

  • Kehadiran sinkron: Gunakan getByRole, getByText, atau query getBy lain saat elemen seharusnya sudah ada. Test akan langsung gagal jika tidak ditemukan.
  • Kemunculan asinkron: Gunakan findByRole atau findByText saat rendering atau interaksi memicu update async.
  • Pengecekan absen: Gunakan queryByText atau queryByTestId ketika sebuah elemen mungkin tidak ada dan hasil null lebih diharapkan daripada munculnya exception.
  • Fallback selector: Gunakan getByTestId secara sengaja. Ini memberikan hook yang stabil untuk kontrol kompleks, namun tidak boleh menggantikan label aksesibilitas di seluruh aplikasi.

Untuk pengujian event yang terfokus, fireEvent.press adalah langsung:

fireEvent.press(screen.getByRole('button', { name: 'Save' }));

Gunakan userEvent ketika versi yang terinstal mendukung urutan interaksi yang lebih realistis. Apapun itu, lakukan assert pada UI yang dihasilkan:

expect(await screen.findByText('Saved')).toBeTruthy();

Handler assertion cocok untuk komponen yang kontrak publiknya berupa event callback. Ini lemah jika hanya dijadikan satu-satunya bukti bahwa user journey berjalan.

Gunakan assertion spesifik daripada snapshot

Assertion yang baik mendeskripsikan layar:

expect(screen.getByText('Account created')).toBeTruthy();
expect(screen.getByRole('button', { name: 'Continue' })).toBeEnabled();

Ini juga bisa memverifikasi status aksesibilitas, seleksi, dan feedback validasi yang terlihat. Hindari mengecek internal wiring:

expect(screen.getByTestId('submit-button').props.onPress).toBeDefined();

Assertion tersebut membuktikan adanya prop, bukan fitur yang berfungsi. Snapshot kecil yang terencana bisa mendeteksi perubahan struktur, sementara snapshot navigasi atau layar yang besar sering kali membuat review berantakan dan memudahkan persetujuan update yang tidak jelas.

Paket Testing Library merupakan bagian dari testing-library organisasi npm. Paket aktifnya meliputi @testing-library/react-native, dengan versi 13.3.3 yang dirilis pada 2026, berdasarkan informasi informasi repositoriproyek tersebut. Konvensi query yang sama membantu di berbagai platform, namun tidak menentukan assertion mana yang mewakili perilaku produk Anda.

Untuk perbandingan praktik testing komponen Jest yang lebih luas, lihat panduan unit testing React. RNTL masih terbatas pada batas komponen yang dirender JavaScript. Izin native, stack navigasi asli, keyboard perangkat, timing frame, dan perilaku memori memerlukan tooling E2E atau performa daripada sekadar menambah component mocks.

Video di bawah ini mendemonstrasikan workflow query dan assertion dalam konteksnya.

Pola Praktis untuk Komponen, Hooks, dan Navigasi

Test suite yang berguna harus mengikuti struktur aplikasi. Presentational component butuh pengujian perilaku langsung, hooks butuh input dan output yang terkontrol, navigasi butuh provider yang cukup realistis, dan native modules butuh mock yang tetap terlihat berbeda dari verifikasi perangkat asli.

Laptop modern di atas meja kayu yang menampilkan React Native code dan mockup aplikasi mobile.

Komponen presentasional

Jaga agar test komponen tetap dekat dengan public contract-nya:

const onSelect = jest.fn();

render(
  <PlanCard
    title="Team"
    description="Shared workspace"
    onSelect={onSelect}
  />
);

fireEvent.press(screen.getByRole('button', { name: 'Choose Team' }));

expect(onSelect).toHaveBeenCalled();

Label harus sesuai dengan UI Anda. Bagian terpenting adalah test tersebut menemukan kontrol seperti cara user atau layanan aksesibilitas melakukannya, serta mengonfirmasi hasil visual atau callback yang relevan. Jangan mock semua child component secara default. Mock boundary yang berat atau tidak terkait hanya jika mereka mengaburkan perilaku yang sedang di-test.

Untuk custom hook, gunakan renderHook ketika versi RNTL yang terinstal menyediakannya:

const { result } = renderHook(() => useSearch());

await act(async () => {
  await result.current.submit('query');
});

expect(result.current.status).toBe('success');

Test hook harus mengontrol boundary network atau repository, bukan mereplikasi seluruh aplikasi. Test screen secara terpisah agar Anda tahu apakah state dari hook tersebut menghasilkan UI yang berguna.

Untuk perilaku navigasi, merender screen di dalam NavigationContainer dan test navigator kecil seringkali lebih berharga daripada melakukan mock pada setiap method navigasi. Tekan kontrol yang terlihat, tunggu konten tujuan, dan assert output dari screen baru tersebut. Sebuah useNavigation mock masih cocok untuk tombol kecil yang tugasnya hanya dispatch typed route, tapi ini tidak akan memvalidasi registrasi route, parameter, atau perilaku nested navigator.

Data async juga butuh disiplin yang sama. Mock respons API atau repository, render screen, assert loading state, resolve request, lalu assert output success atau error. Gunakan findBy mencari elemen yang diharapkan nantinya dan membuat request yang ditolak menjadi eksplisit, jika tidak, test bisa lolos padahal komponen tidak pernah mencapai branch yang dituju.

Mock native module

Mock untuk AsyncStorage, permissions, kamera, biometrik, dan platform API sangat berguna untuk test JavaScript yang deterministik. Ini bukan bukti bahwa fitur native berfungsi. Pastikan perilaku mock sesuai dengan kontrak module, reset calls antar test, dan sertakan failure responses alih-alih hanya memodelkan happy path.

Skenario Terbaik dengan RNTL Perlu Validasi E2E
Validasi form dan error yang terlihat Ya Biasanya tidak
UI loading, success, dan error dari repository yang di-mock Ya Untuk alur produksi kritis
Navigasi antar screen terdaftar Ya, dengan test navigator Ya, jika gesture, deep link, atau perilaku platform penting
Keputusan state AsyncStorage Ya, dengan mock yang terkontrol Ya, saat launch dan persistensi berinteraksi dengan native lifecycle
Kamera, biometrik, permission, atau platform API JS fallback dan logika branching Ya, pada device asli atau representatif
Layout, performa rendering, dan native code Tidak Ya, dengan perangkat atau tooling khusus

Batasan ini sangat praktis: mock dependensinya untuk menguji logika JavaScript Anda, lalu jalankan pengujian perangkat untuk memastikan perilaku asli dependensi tersebut.

Debugging Flaky Tests di CI dan Pengecekan Performa

Flaky test sering kali disebabkan oleh waktu yang tidak terkontrol, shared state, atau assertion yang race dengan UI. Identifikasi kondisi mana yang sedang terjadi sebelum menaikkan timeout. Timeout yang lebih lama bisa menyembunyikan masalah scheduling dan membuat suite lebih lambat.

Gunakan findBy untuk elemen yang diharapkan muncul setelah update. Gunakan waitFor untuk kondisi state atau mock calls. Jika fake timers diaktifkan, advance timer tersebut saat interaksi membutuhkannya dan pulihkan real timer setelahnya. Sebuah act warning berarti React mendeteksi update di luar boundary interaksi yang diharapkan. Perbaiki awaityang hilang, interaksi user, atau timer flush alih-alih menekan warning tersebut.

Buat kegagalan CI dapat direproduksi

CI job yang andal melakukan instalasi dari lockfile, menjalankan perintah Jest yang sama seperti di lokal, dan mengisolasi mock state. Bersihkan mock calls antar test, reset module saat module-level state memengaruhi perilaku, dan hapus ketergantungan pada urutan eksekusi. Jest caching mempercepat feedback, tetapi perubahan dependensi atau konfigurasi memerlukan invalidasi cache yang tepat.

Kegagalan yang hanya terjadi di CI memerlukan perbandingan environment sebelum menulis ulang komponen. Periksa Node, package manager, pengaturan Jest worker, konfigurasi timer, dan environment variables. Reproduksi command yang sama secara lokal jika memungkinkan, lalu sederhanakan test yang gagal ke interaksi terkecil yang menunjukkan perbedaannya.

Observability mengisi celah yang berbeda. Monitoring kesehatan aplikasi menyediakan context error produksi yang tidak bisa direproduksi oleh mocked component tests, termasuk kegagalan yang terkait dengan perangkat asli dan integrasi native.

Alur yang sensitif terhadap keamanan butuh batasan kedua. Gunakan component tests untuk validasi dan transisi state, lalu tambahkan coverage level perangkat untuk proses handoff dan perilaku native. Untuk alur code sekali jalan, lihat panduan tentang cara test alur verifikasi SMS ketika integrasi tersebut merupakan bagian dari alur tersebut.

Anggap performa sebagai pengukuran, bukan assertion

Functional test dapat mengonfirmasi bahwa sebuah list berhasil render. Namun, ia tidak bisa menentukan secara andal apakah sebuah refactor mengubah durasi atau jumlah render, karena runtime test menambah noise. Reassure mengukur nilai-nilai tersebut untuk sebuah skenario, mengulang skenario untuk mengurangi varians, dan menerapkan analisis statistik sebelum melaporkan perubahan yang berarti. Dokumentasi dokumentasi pengujian performa juga mencakup pelaporan yang sesuai untuk CI dan review pull-request.

Hindari assertion statis seperti “render harus selesai di bawah ambang batas tertentu.” Worker CI yang sibuk bisa memicu false failure, sementara ambang batas yang terlalu longgar bisa melewatkan regresi nyata. Gunakan pengukuran berulang untuk sinyal regresi, lalu periksa komponen dan profil perangkat saat perbandingan menunjukkan perbedaan yang signifikan.

Aturan pengukuran: Test fungsional menjawab apakah perilaku sudah benar. Tool performa menjawab apakah skenario yang diukur mengalami perubahan. Pisahkan kedua pertanyaan tersebut.

Kesimpulan dan Langkah Selanjutnya

React Native Testing Library masuk dalam layer strategi test yang luas dan cepat. Ini harus mencakup perilaku komponen, perubahan state yang terlihat, hasil aksesibilitas, validasi, state data mock, dan integrasi antar komponen JavaScript. Fokuskan test pada apa yang bisa diobservasi user, dan pastikan failure merujuk pada perilaku spesifik, bukan pada seluruh render tree yang besar.

Lapisan berbasis perangkat yang lebih kecil harus melindungi alur kerja di mana mock bisa menyesatkan. React Native’s ringkasan testing menyatakan bahwa RNTL tidak menyediakan runtime React Native penuh dan tidak bisa mengetes fitur native. Panduan yang sama merekomendasikan pairing component test dengan tool E2E seperti Detox untuk flow kritikal termasuk autentikasi, pembayaran, dan fungsi inti aplikasi.

Jalur migrasi praktis

Anda tidak perlu menulis ulang seluruh suite dalam satu waktu.

  1. Pertahankan business test yang bernilai. Pindahkan pure state dan domain logic ke unit test yang terfokus agar memberikan feedback yang jelas.
  2. Prioritaskan mengganti assertion implementasi. Ubah pengecekan prop dan internal-state menjadi output visual, status aksesibilitas, dan hasil interaksi.
  3. Perkecil ukuran snapshot. Simpan hanya snapshot yang mudah dipahami dan dikelola oleh reviewer.
  4. Tambahkan cakupan native boundary. Untuk setiap module yang di-mock, identifikasi perilaku device yang masih perlu divalidasi.
  5. Lindungi critical journeys. Tambahkan cakupan E2E untuk autentikasi, pembayaran, navigasi utama, izin, dan flow lain di mana perilaku native dapat mengubah hasil.
  6. Ukur screen sensitif secara terpisah. Gunakan perbandingan performa berulang untuk list, feed, dan render path yang berat daripada sekadar menebak dari durasi Jest.

Untuk kepercayaan saat rilis, hubungkan suite ke integrasi testing CI/CD dan memerlukan layer pengujian yang tepat sebelum rilis. Jika perbaikan JavaScript atau aset harus sampai ke pengguna setelah validasi, Capgo dapat mengirimkan web bundle terverifikasi ke channel tertentu untuk aplikasi CapacitorJS dan Electron, lengkap dengan kontrol rollout dan proteksi rollback. Workflow pengiriman tersebut tidak menggantikan pengujian perangkat React Native, namun mengilustrasikan prinsip yang sama: validasi perilaku pada layer tempat ia berjalan.

Pertanyaan yang tepat bukanlah apakah React Native Testing Library bisa menguji seluruh aplikasi Anda. Tidak bisa, dan batasan resminya sangat berguna. Pertanyaan yang benar adalah apakah setiap risiko penting sudah memiliki pengujian yang berjalan di lingkungan yang mampu mengungkapkannya.


Capgo menghubungkan perubahan JavaScript dan aset yang telah divalidasi ke pengiriman terkontrol untuk tim CapacitorJS dan Electron, dengan channel tertarget, visibilitas rollout, dan proteksi rollback. Kunjungi Capgo untuk melihat bagaimana fitur ini dapat melengkapi workflow pengujian komponen, E2E, dan CI Anda.

Live update untuk aplikasi Capacitor

Saat bug di web layer sudah live, kirim perbaikannya lewat Capgo alih-alih menunggu berhari-hari untuk persetujuan app store. Pengguna menerima update di background, sementara perubahan native tetap di jalur review normal.

Terbaru dari Blog kami

Capgo memberikan insight terbaik yang Anda butuhkan untuk membuat aplikasi mobile yang benar-benar profesional.