Pengujian Unit Dalam Aplikasi React Native
Diterbitkan: 2022-03-10React Native adalah salah satu framework yang paling banyak digunakan untuk membangun aplikasi mobile. Tutorial ini ditujukan untuk para developer yang ingin mulai menguji aplikasi React Native yang mereka bangun. Kami akan menggunakan kerangka kerja pengujian Jest dan Enzim.
Dalam artikel ini, kita akan mempelajari prinsip-prinsip inti pengujian, menjelajahi berbagai pustaka untuk menguji aplikasi, dan melihat cara menguji unit (atau komponen) aplikasi React Native. Dengan bekerja dengan aplikasi React Native, kami akan memperkuat pengetahuan kami tentang pengujian.
Catatan: Pengetahuan dasar tentang JavaScript dan React Native akan sangat bermanfaat saat Anda mengerjakan tutorial ini.
Apa itu Pengujian Unit?
Pengujian unit adalah tingkat pengujian di mana masing-masing komponen perangkat lunak diuji. Kami melakukannya untuk memastikan bahwa setiap komponen berfungsi seperti yang diharapkan. Komponen adalah bagian terkecil dari perangkat lunak yang dapat diuji.
Sebagai ilustrasi, mari buat komponen Button
dan simulasikan pengujian unit:
import React from 'react'; import { StyleSheet, Text, TouchableOpacity } from 'react-native'; function AppButton({ onPress }) { return ( <TouchableOpacity style={[styles.button, { backgroundColor: colors[color] }]} onPress={onPress} > <Text style={styles.text}>Register</Text> </TouchableOpacity> ); } const styles = StyleSheet.create({ button: { backgroundColor: red; borderRadius: 25, justifyContent: 'center', alignItems: 'center', }, text: { color: #fff } }) export default AppButton;
Komponen Button
ini memiliki teks dan fungsi onPress
. Mari kita uji komponen ini untuk melihat apa itu pengujian unit.
Pertama, mari buat file pengujian, bernama Button.test.js
:
it('renders correctly across screens', () => { const tree = renderer.create(<Button />).toJSON(); expect(tree).toMatchSnapshot(); });
Di sini, kami menguji untuk melihat apakah komponen Button
kami dirender sebagaimana mestinya di semua layar aplikasi. Inilah yang dimaksud dengan pengujian unit: menguji komponen aplikasi untuk memastikan mereka berfungsi sebagaimana mestinya.
Pengujian Unit Dalam Aplikasi React Native
Aplikasi React Native dapat diuji dengan berbagai alat, beberapa di antaranya adalah sebagai berikut:
- WebDriver
Alat pengujian sumber terbuka untuk aplikasi Node.js ini juga digunakan untuk menguji aplikasi React Native. - Mimpi buruk
Ini mengotomatiskan operasi pengujian di browser. Menurut dokumentasi, "tujuannya adalah untuk mengekspos beberapa metode sederhana yang meniru tindakan pengguna (sepertigoto
,type
danclick
), dengan API yang terasa sinkron untuk setiap blok skrip, daripada callback yang sangat bersarang." - Bersenda gurau
Ini adalah salah satu perpustakaan pengujian paling populer di luar sana dan yang akan kita fokuskan hari ini. Seperti React, itu dikelola oleh Facebook dan dibuat untuk menyediakan pengaturan "konfigurasi nol" untuk kinerja maksimum. - Moka
Mocha adalah perpustakaan populer untuk menguji aplikasi React dan React Native. Ini telah menjadi alat pengujian pilihan bagi pengembang karena betapa mudahnya mengatur dan menggunakannya dan seberapa cepatnya. - Melati
Menurut dokumentasinya, Jasmine adalah kerangka kerja pengembangan berbasis perilaku untuk menguji kode JavaScript.
Pengantar Jest Dan Enzim
Menurut dokumentasinya, "Jest adalah kerangka kerja pengujian JavaScript yang menyenangkan dengan fokus pada kesederhanaan". Ia bekerja dengan konfigurasi nol. Setelah instalasi (menggunakan manajer paket seperti npm atau Yarn), Jest siap digunakan, tanpa perlu instalasi lain.
Enzyme adalah framework pengujian JavaScript untuk aplikasi React Native. (Jika Anda bekerja dengan React daripada React Native, panduan tersedia.) Kami akan menggunakan Enzyme untuk menguji unit output aplikasi kami. Dengan itu, kita dapat mensimulasikan runtime aplikasi.
Mari kita mulai dengan menyiapkan proyek kita. Kami akan menggunakan aplikasi Done With It di GitHub. Ini adalah pasar aplikasi React Native. Mulailah dengan mengkloningnya, navigasikan ke folder, dan instal paket dengan menjalankan yang berikut untuk npm…
npm install
… atau ini untuk Benang:
yarn install
Perintah ini akan menginstal semua paket di aplikasi kita. Setelah selesai, kami akan menguji konsistensi UI aplikasi kami menggunakan snapshot, yang dibahas di bawah ini.
Snapshots Dan Konfigurasi Jest
Di bagian ini, kami akan menguji sentuhan pengguna dan UI komponen aplikasi dengan menguji snapshot menggunakan Jest.
Sebelum melakukan itu, kita perlu menginstal Jest dan dependensinya. Untuk menginstal Jest for Expo React Native, jalankan perintah berikut:
yarn add jest-expo --dev
Ini menginstal jest-expo
di direktori aplikasi kita. Selanjutnya, kita perlu memperbarui file package.json
kita untuk memiliki skrip pengujian:
"scripts": { "test" "jest" }, "jest": { "preset": "jest-expo" }
Dengan menambahkan perintah ini, kami memberi tahu Jest paket mana yang harus didaftarkan di aplikasi kami dan di mana.
Selanjutnya adalah menambahkan paket lain ke aplikasi kita yang akan membantu Jest untuk melakukan tes yang komprehensif. Untuk npm, jalankan ini…
npm i react-test-renderer --save-dev
… dan untuk Benang, ini:
yarn add react-test-renderer --dev
Kami masih memiliki sedikit konfigurasi yang harus dilakukan di file package.json
kami. Menurut dokumentasi Expo React Native, kita perlu menambahkan konfigurasi transformIgnorePattern
yang mencegah tes berjalan di Jest setiap kali file sumber cocok dengan tes (yaitu jika tes dilakukan dan file serupa ditemukan di node modules
proyek).
"jest": { "preset": "jest-expo", "transformIgnorePatterns": [ "node_modules/(?!(jest-)?react-native|react-clone-referenced-element|@react-native-community|expo(nent)?|@expo(nent)?/.*|react-navigation|@react-navigation/.*|@unimodules/.*|unimodules|sentry-expo|native-base|@sentry/.*)" ] }
Sekarang, mari buat file baru, bernama App.test.js
, untuk menulis pengujian pertama kita. Kami akan menguji apakah App
kami memiliki satu elemen anak di pohonnya:
import React from "react"; import renderer from "react-test-renderer"; import App from "./App.js" describe("<App />", () => { it('has 1 child', () => { const tree = renderer.create(<App />).toJSON(); expect(tree.children.length).toBe(1); }); });
Sekarang, jalankan yarn test
atau yang setara dengan npm. Jika App.js
memiliki elemen anak tunggal, pengujian kami harus lulus, yang akan dikonfirmasi di antarmuka baris perintah.
Dalam kode di atas, kami telah mengimpor React
dan react-test-renderer
, yang membuat pengujian kami untuk Expo
. Kami telah mengonversi pohon komponen <App />
ke JSON, lalu meminta Jest untuk melihat apakah jumlah komponen turunan yang dikembalikan di JSON sama dengan yang kami harapkan.
Lebih Banyak Tes Snapshot
Seperti yang dikatakan David Adeney:
“Tes snapshot memastikan bahwa antarmuka pengguna (UI) aplikasi web tidak berubah secara tiba-tiba. Ini menangkap kode komponen pada suatu waktu, sehingga kami dapat membandingkan komponen dalam satu keadaan dengan kemungkinan keadaan lain yang mungkin diperlukan.”
Ini dilakukan terutama ketika sebuah proyek melibatkan gaya global yang digunakan di banyak komponen. Mari kita tulis pengujian snapshot untuk App.js
untuk menguji konsistensi UI-nya:
it('renders correctly across screens', () => { const tree = renderer.create( ).toJSON(); expect(tree).toMatchSnapshot(); });
it('renders correctly across screens', () => { const tree = renderer.create( ).toJSON(); expect(tree).toMatchSnapshot(); });
Tambahkan ini ke tes yang telah kami tulis, lalu jalankan yarn test
(atau yang setara dengan npm). Jika tes kami lulus, kami akan melihat ini:
PASS src/App.test.js √ has 1 child (16ms) √ renders correctly (16ms) Test Suites: 1 passed, 1 total Tests: 2 passed, 2 total Snapshots: 1 total Time: 24s
Ini memberitahu kita bahwa tes kami lulus dan waktu yang dibutuhkan. Hasil Anda akan terlihat serupa jika tes lulus.
Mari kita beralih ke mengejek beberapa fungsi di Jest.
Mengejek Panggilan API
Menurut dokumentasi Jest:
Fungsi tiruan memungkinkan Anda menguji tautan antar kode dengan menghapus implementasi sebenarnya dari suatu fungsi, menangkap panggilan ke fungsi tersebut (dan parameter yang diteruskan dalam panggilan tersebut), menangkap instance fungsi konstruktor saat dipakai dengan `baru`, dan mengizinkan pengujian- konfigurasi waktu nilai kembali.
Sederhananya, tiruan adalah salinan dari suatu objek atau fungsi tanpa cara kerja sebenarnya dari fungsi itu. Ini meniru fungsi itu.
Mock membantu kami menguji aplikasi dalam banyak cara, tetapi manfaat utamanya adalah mereka mengurangi kebutuhan kami akan dependensi.
Mengolok-olok biasanya dapat dilakukan dengan salah satu dari dua cara. Salah satunya adalah membuat fungsi tiruan yang disuntikkan ke dalam kode yang akan diuji. Yang lainnya adalah menulis fungsi tiruan yang menimpa paket atau ketergantungan yang dilampirkan ke komponen.
Sebagian besar organisasi dan pengembang lebih suka menulis tiruan manual yang meniru fungsionalitas dan menggunakan data palsu untuk menguji beberapa komponen.
React Native menyertakan fetch
di objek global. Untuk menghindari membuat panggilan API nyata dalam pengujian unit kami, kami mengejeknya. Di bawah ini adalah cara untuk mengejek semua, jika bukan sebagian besar, panggilan API kami di React Native, dan tanpa memerlukan dependensi:
global.fetch = jest.fn(); // mocking an API success response once fetch.mockResponseIsSuccess = (body) => { fetch.mockImplementationForOnce ( () => Promise.resolve({json: () => Promise.resolve(JSON.parse(body))}) ); }; // mocking an API failure response for once fetch.mockResponseIsFailure = (error) => { fetch.mockImplementationForOnce( () => Promise.reject(error) ); };
Di sini, kami telah menulis fungsi yang mencoba mengambil API satu kali. Setelah melakukan ini, ia mengembalikan janji, dan ketika diselesaikan, ia mengembalikan tubuh di JSON. Ini mirip dengan respons tiruan untuk transaksi pengambilan yang gagal — ini mengembalikan kesalahan.
Di bawah ini adalah komponen product
dari aplikasi kami, yang berisi objek product
dan mengembalikan informasi sebagai props
.
import React from 'react'; const Product = () => { const product = { name: 'Pizza', quantity: 5, price: '$50' } return ( <> <h1>Name: {product.name}</h1> <h1>Quantity: {product.quantity}</h1> <h1>Price: {product.price}</h1> </> ); } export default Product;
Mari kita bayangkan kita mencoba menguji semua komponen produk kita. Mengakses database kami secara langsung bukanlah solusi yang layak. Di sinilah mengolok-olok datang ke dalam bermain. Dalam kode di bawah ini, kami mencoba untuk mengolok-olok komponen produk dengan menggunakan Jest untuk menggambarkan objek dalam komponen.
describe("", () => { it("accepts products props", () => { const wrapper = mount(<Customer product={product} />); expect(wrapper.props().product).toEqual(product); }); it("contains products quantity", () => { expect(value).toBe(3); }); });
Kami menggunakan describe
dari Jest untuk mendikte tes yang ingin kami lakukan. Pada pengujian pertama, kita mengecek apakah objek yang kita lewati sama dengan props yang kita ejek.
Pada tes kedua, kami melewati alat peraga customer
untuk memastikan itu adalah produk dan cocok dengan tiruan kami. Dalam melakukannya, kita tidak perlu menguji semua komponen produk kita, dan kita juga dapat mencegah bug dalam kode kita.
Mengejek Permintaan API Eksternal
Sampai sekarang, kami telah menjalankan pengujian untuk panggilan API dengan elemen lain di aplikasi kami. Sekarang mari kita tiru panggilan API eksternal. Kita akan menggunakan Axios. Untuk menguji panggilan eksternal ke API, kami harus meniru permintaan kami dan juga mengelola respons yang kami dapatkan. Kita akan menggunakan axios-mock-adapter
untuk mengejek Axios. Pertama, kita perlu menginstal axios-mock-adapter
dengan menjalankan perintah di bawah ini:
yarn add axios-mock-adapter
Hal berikutnya yang harus dilakukan adalah membuat tiruan kami:
import MockAdapter from 'axios-mock-adapter'; import Faker from 'faker' import ApiClient from '../constants/api-client'; import userDetails from 'jest/mockResponseObjects/user-objects'; let mockApi = new MockAdapter(ApiClient.getAxiosInstance()); let validAuthentication = { name: Faker.internet.email(), password: Faker.internet.password() mockApi.onPost('requests').reply(config) => { if (config.data === validAuthentication) { return [200, userDetails]; } return [400, 'Incorrect username and password']; });
Di sini, kami memanggil ApiClient
dan meneruskan instance Axios ke sana untuk mengejek kredensial pengguna. Kami menggunakan paket bernama faker.js untuk menghasilkan data pengguna palsu, seperti alamat email dan kata sandi.
Mock berperilaku seperti yang kita harapkan dari API. Jika permintaan berhasil, kami akan mendapatkan respons dengan kode status 200 untuk OK. Dan kami akan mendapatkan kode status 400 untuk permintaan buruk ke server, yang akan dikirim dengan JSON dengan pesan "Nama pengguna dan kata sandi salah".
Sekarang tiruan kita sudah siap, mari kita tulis pengujian untuk permintaan API eksternal. Seperti sebelumnya, kita akan menggunakan snapshot.
it('successful sign in with correct credentials', async () => { await store.dispatch(authenticateUser('[email protected]', 'password')); expect(getActions()).toMatchSnapshot(); }); it('unsuccessful sign in with wrong credentials', async () => { await store.dispatch(authenticateUser('[email protected]', 'wrong credential')) .catch((error) => { expect(errorObject).toMatchSnapshot(); });
Di sini, kami menguji proses masuk yang berhasil dengan kredensial yang benar, menggunakan async await
untuk menahan input kami. Sementara itu, fungsi authenticateUser
dari Jest mengautentikasi permintaan dan memastikannya cocok dengan snapshot kami sebelumnya. Selanjutnya, kami menguji proses masuk yang gagal jika terjadi kredensial yang salah, seperti alamat email atau kata sandi, dan kami mengirimkan kesalahan sebagai tanggapan.
Sekarang, jalankan yarn test
atau npm test
. Saya yakin semua ujian Anda akan lulus.
Mari kita lihat cara menguji komponen di perpustakaan manajemen negara, Redux.
Menguji Tindakan Redux Dan Peredam Menggunakan Snapshot
Tidak dapat disangkal bahwa Redux adalah salah satu state manager yang paling banyak digunakan untuk aplikasi React. Sebagian besar fungsi di Redux melibatkan dispatch
, yang merupakan fungsi dari toko Redux yang digunakan untuk memicu perubahan status aplikasi. Menguji Redux bisa jadi rumit karena actions
Redux tumbuh dengan cepat dalam ukuran dan kompleksitas. Dengan snapshot Jest, ini menjadi lebih mudah. Sebagian besar pengujian dengan Redux bermuara pada dua hal:
- Untuk menguji
actions
, kami membuatredux-mock-store
dan mengirimkan tindakan. - Untuk menguji reduksi, kami mengimpor
reducer
dan meneruskan objek status dan tindakan ke sana.
Di bawah ini adalah tes Redux dengan snapshot. Kami akan menguji tindakan yang dikirim dengan mengautentikasi pengguna di SIGN-IN
dan melihat bagaimana tindakan LOGOUT
ditangani oleh peredam user
.
import mockStore from 'redux-mock-store'; import { LOGOUT } from '../actions/logout'; import User from '../reducers/user'; import { testUser } from 'jest/mock-objects'; describe('Testing the sign in authentication', () => { const store = mockStore(); it('user attempts with correct password and succeeds', async () => { await store.dispatch(authenticateUser('[email protected]', 'password')); expect(store.getActions()).toMatchSnapshot(); }); }); describe('Testing reducers after user LOGS OUT', () => { it('user is returned back to initial app state', () => { expect(user(testUser, { type: LOGOUT })).toMatchSnapshot(); }); });
Pada pengujian pertama, kami menjelaskan autentikasi masuk dan membuat toko tiruan. Kami melakukan ini dengan terlebih dahulu mengimpor mockStore
dari Redux, lalu mengimpor metode bernama testUser
dari Jest untuk membantu kami mengejek pengguna. Selanjutnya, kami menguji kapan pengguna berhasil masuk ke aplikasi menggunakan alamat email dan kata sandi yang cocok dengan yang ada di toko snapshot kami. Jadi, snapshot memastikan bahwa objek yang dimasukkan pengguna cocok setiap kali pengujian dijalankan.
Pada pengujian kedua, kami menguji kapan pengguna logout. Setelah snapshot peredam kami mengonfirmasi bahwa pengguna telah keluar, itu kembali ke keadaan awal aplikasi.
Selanjutnya, kami menguji dengan menjalankan yarn test
. Jika tes telah lulus, kita akan melihat hasil berikut:
PASS src/redux/actions.test.js √ user attempts with correct password and succeeds (23ms) √ user is returned back to initial app state (19ms) Test Suites: 1 passed, 1 total Tests: 2 passed, 2 total Snapshots: 2 total Time: 31s
Kesimpulan
Dengan Jest, menguji aplikasi React Native tidak pernah semudah ini, terutama dengan snapshot, yang memastikan bahwa UI tetap konsisten terlepas dari gaya global. Juga, Jest memungkinkan kita untuk mengejek panggilan dan modul API tertentu dalam aplikasi kita. Kita dapat mengambil ini lebih jauh dengan menguji komponen aplikasi React Native.
Sumber Daya Lebih Lanjut
- “Panduan Praktis untuk Menguji Aplikasi React Native Dengan Jest”, David Adeneye, Smashing Magazine
- Dokumentasi lelucon
- “Pengujian Dengan Jest”, Expo React Native dokumentasi
- “Belajar Menguji Bereaksi Asli Dengan Jest”, Jason Gaare