ReactJS #28: Testing Sederhana dengan React Testing Library


ReactJS #28: Testing Sederhana

Dengan React Testing Library
(Opsional, untuk yang Ingin Lebih Profesional)

Halo, penguji kode! 🧪

Setelah aplikasi React-mu jadi, kamu pasti ingin memastikan semuanya berfungsi dengan benar. Apalagi jika aplikasi sudah besar, sulit mengecek satu per satu secara manual. Di sinilah testing (pengujian) berperan. Ibarat guru yang memeriksa PR murid, kita bisa menulis kode yang secara otomatis memeriksa apakah komponen kita bekerja sesuai harapan.

💡 Analogi: Bayangkan kamu membuat mesin penjual minuman. Setelah jadi, kamu harus mengecek apakah saat tombol ditekan, minuman keluar dengan benar. Daripada setiap kali kamu tes manual, lebih baik buat robot penguji yang melakukan pengecekan otomatis. React Testing Library adalah robot penguji untuk komponen React-mu.

🧐 Apa Itu React Testing Library?

React Testing Library adalah seperangkat alat untuk menguji komponen React. Ia mendorong kita untuk menguji komponen dari sudut pandang pengguna, bukan dari detail implementasi. Jadi kita akan mencari elemen di layar (seperti tombol, teks) dan mensimulasikan interaksi (klik, ketik), lalu memeriksa hasilnya.

React Testing Library sudah termasuk saat kita membuat proyek dengan Create React App. Kita juga punya Jest sebagai test runner (yang menjalankan tes dan memberi laporan).

📁 Lokasi File Tes

Biasanya file tes diletakkan di dekat komponen yang diuji, dengan nama Component.test.js atau Component.spec.js. Contoh: untuk komponen Button.js, buat Button.test.js di folder yang sama.

Atau bisa juga di folder __tests__. Create React App akan otomatis menemukan file-file ini saat kita menjalankan npm test.

🔧 Menjalankan Tes

Untuk menjalankan tes, gunakan perintah:

npm test

Perintah ini akan menjalankan Jest dalam mode watch (memantau perubahan). Setiap kali kamu mengubah kode atau tes, tes akan dijalankan ulang. Tekan q untuk keluar, a untuk jalankan semua tes.

🧪 Contoh 1: Menguji Komponen Sederhana

Buat komponen Counter.js:

import { useState } from 'react'; function Counter() { const [count, setCount] = useState(0); return ( <div> <p>Kamu sudah klik {count} kali</p> <button onClick={() => setCount(count + 1)}>Klik aku</button> </div> ); } export default Counter;

Buat file tes Counter.test.js di folder yang sama:

import { render, screen, fireEvent } from '@testing-library/react'; import Counter from './Counter'; test('menampilkan teks awal 0 dan tombol', () => { render(<Counter />); // Cari teks yang mengandung "Kamu sudah klik 0 kali" const textElement = screen.getByText(/Kamu sudah klik 0 kali/i); expect(textElement).toBeInTheDocument(); // Cari tombol dengan teks "Klik aku" const buttonElement = screen.getByRole('button', { name: /Klik aku/i }); expect(buttonElement).toBeInTheDocument(); }); test('tombol klik menambah counter', () => { render(<Counter />); const buttonElement = screen.getByRole('button', { name: /Klik aku/i }); fireEvent.click(buttonElement); const textElement = screen.getByText(/Kamu sudah klik 1 kali/i); expect(textElement).toBeInTheDocument(); });

Penjelasan:

  • render – merender komponen ke dalam lingkungan tes (virtual DOM).
  • screen.getByText – mencari elemen berdasarkan teks (bisa pakai regex).
  • screen.getByRole – mencari elemen berdasarkan peran aksesibilitas (bagus untuk tombol).
  • fireEvent.click – mensimulasikan klik pada tombol.
  • expect(...).toBeInTheDocument() – memastikan elemen ada di DOM (matchers dari jest-dom).

Jalankan npm test, dan lihat hasilnya! 🌟

🖱️ Menguji Interaksi Pengguna dengan user-event

fireEvent cepat, tapi kurang realistis. Ada library @testing-library/user-event yang lebih mirip interaksi pengguna sungguhan (misal mengetik, memilih).

Instal (sudah include di CRA sebenarnya):

npm install --save-dev @testing-library/user-event

Contoh untuk form input:

import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import Form from './Form'; test('bisa mengetik di input', async () => { const user = userEvent.setup(); render(<Form />); const input = screen.getByLabelText(/Nama/i); await user.type(input, 'Budi'); expect(input).toHaveValue('Budi'); });

Perhatikan await user.type(...) karena interaksi user-event bersifat asinkron.

📡 Menguji Komponen yang Mengambil Data (Mock API)

Komponen sering mengambil data dari API. Saat tes, kita tidak ingin benar-benar memanggil API (lambat, tidak bisa diandalkan). Kita bisa mock (meniru) fungsi fetch.

Contoh komponen UserList.js yang fetch daftar pengguna:

import { useState, useEffect } from 'react'; function UserList() { const [users, setUsers] = useState([]); const [loading, setLoading] = useState(true); useEffect(() => { fetch('https://jsonplaceholder.typicode.com/users') .then(res => res.json()) .then(data => { setUsers(data); setLoading(false); }); }, []); if (loading) return <p>Memuat...</p> return ( <ul> {users.map(user => <li key={user.id}>{user.name}</li>)} </ul> ); }

Buat tes dengan mock fetch:

import { render, screen, waitFor } from '@testing-library/react'; import UserList from './UserList'; // Mock fetch global global.fetch = jest.fn(() => Promise.resolve({ json: () => Promise.resolve([ { id: 1, name: 'Budi' }, { id: 2, name: 'Siti' } ]) }) ); beforeEach(() => { fetch.mockClear(); }); test('menampilkan daftar pengguna setelah fetch', async () => { render(<UserList />); // Awalnya loading expect(screen.getByText(/Memuat.../i)).toBeInTheDocument(); // Tunggu sampai daftar muncul await waitFor(() => { expect(screen.getByText('Budi')).toBeInTheDocument(); expect(screen.getByText('Siti')).toBeInTheDocument(); }); expect(fetch).toHaveBeenCalledTimes(1); expect(fetch).toHaveBeenCalledWith('https://jsonplaceholder.typicode.com/users'); });

Kita menggunakan waitFor untuk menunggu hingga elemun muncul (karena asinkron).

💡 Ingat: Setelah tes selesai, kita kembalikan fetch ke aslinya jika perlu. Tapi karena kita mock global, hati-hati jangan sampai mock mengganggu tes lain. Biasanya mock di-reset di afterEach atau menggunakan jest.clearAllMocks().

🧩 Apa yang Perlu Diuji?

  • Rendering dasar: Apakah komponen muncul dengan benar (teks, tombol)?
  • Interaksi pengguna: Apakah klik, ketik, submit berfungsi?
  • Kasus tepi (edge cases): Apa yang terjadi jika data kosong? Jika error?
  • Kondisi loading dan error: Apakah tampilan loading muncul, lalu hilang setelah data datang?

🧪 Latihan: Menguji Komponen Todo

Ambil komponen TodoList dari artikel #15 (atau buat sederhana). Tulis tes untuk:

  1. Menampilkan daftar tugas awal.
  2. Menambahkan tugas baru (simulasi ketik dan klik tombol).
  3. Menandai tugas selesai (klik checkbox) dan memastikan coretan muncul.
  4. Menghapus tugas.

Gunakan userEvent untuk simulasi ketik dan klik.

⚠️ Tips: Saat menguji komponen yang menggunakan state, pastikan untuk menggunakan await jika ada perubahan state asinkron (misal setelah klik, state update butuh waktu).

🚀 Kesimpulan

  • React Testing Library membantu kita menguji komponen dari perspektif pengguna.
  • Gunakan render, screen, fireEvent atau userEvent untuk interaksi.
  • Mock fetch untuk menguji komponen yang bergantung pada API.
  • Testing membuat aplikasi lebih andal dan memudahkan pengembangan fitur baru tanpa merusak yang lama.

Meskipun opsional, belajar testing akan membawamu ke level profesional. Selamat mencoba!

Di artikel selanjutnya kita akan membuat Aplikasi Blog Sederhana dengan API WordPress sebagai proyek akhir. Sampai jumpa!

Lebih baru Lebih lama

نموذج الاتصال