Anda mungkin berada di salah satu situasi saat ini. Entah proyek JavaScript Anda hampir tidak memiliki tes dan setiap refactor terasa berisiko, atau Anda sudah memiliki tes dan setengah dari mereka lambat, rapuh, dan sulit dipercaya.
itu menjadi semakin buruk di Capacitor dan Electron Aplikasi. Fitur sederhana dapat menyentuh logika bisnis bersamaan, API browser, plugin native, file lokal, IPC, dan layanan jarak jauh dalam aliran yang sama. Jika Anda menguji bagian-bagian tersebut dengan cara yang salah, suite Anda akan menjadi labirin ketergantungan palsu. Jika Anda mengujinya dengan cara yang benar, Anda akan mendapatkan feedback cepat pada logika yang rusak.
Unit Test JavaScript yang baik tidak dimulai dengan sintaks matcher yang cerdas. Ini dimulai dengan batasan yang disiplin: uji logika murni secara langsung, isolasi efek samping, dan hindari menulis tes yang menghancurkan ketika Anda mengubah nama fungsi internal.
Tabel Konten
- Pemilihan Framework Pengujian JavaScript
- Penyiapan Proyek dan Tes Pertama
- Menguasai Mocks dan Asinkron Code
- Strategi Lanjutan untuk Tes yang Kuat
- Menguji untuk CI, Capacitor, dan Aplikasi Electron
- Mengapa Pentingnya Pengujian Unit JavaScript
Pemilihan Framework Pengujian JavaScript
Proyek JavaScript Profesional Memerlukan Pengujian yang Nyata. Skrip Ad Hoc dan Pengecekan Konsol Manual Tidak Mampu Menjangkau Ketika Banyak Insinyur Mengakses Sama Basis Kode. Anda Memerlukan Penemuan Pengujian, Asertasi, Pengelolaan Asinkron, Mock, dan Cara Menjalankan Semua Hal Secara Konsisten di Pengembangan Lokal dan CI.
Panduan Saat Ini Terus Berkonvergensi ke Pilihan Utama yang Terbatas. Jest, Mocha, dan Jasmine seringkali Dihimpit Sebagai Framework Utama, dengan Jest seringkali dipilih karena struktur tes bawaan, asertasi, pemalsuan, dan dukungan async dalam satu paket, seperti yang ditunjukkan di sini Lab Tes JavaScript Pluralsight.

Mengapa suatu framework tidak optional
Kesalahan pertama tim adalah menganggap tes unit sebagai kegiatan sampingan. Biasanya hal ini menyebabkan penamaan file tidak konsisten, asertasi kustom yang tidak diingat, dan bantuan yang hanya dipahami oleh satu orang
Suatu framework memberikan Anda bahasa yang sama:
- Struktur Tes dengan
describeatautestAsertasiit - dengan matcher yang dapat dibaca with
- Hook untuk pengaturan dan penghapusan
- Dukungan Asinkron untuk promise dan timer
- Alat Palsu untuk dependensi luar
Jika tim Anda juga memerlukan pandangan yang lebih luas tentang otomatisasi tes di luar pekerjaan unit, Capgo memiliki gambaran yang berguna tentang pengujian otomatis dalam alur kerja pengiriman aplikasi.
Jest vs Mocha secara singkat
Jest dan Mocha mewakili dua filosofi yang berbeda.
Jest adalah pilihan semua dalam satu. Ini dilengkapi dengan sebagian besar yang dibutuhkan tim pada hari pertama.
Mocha lebih modular. Ini memberikan Anda runner dan mengharapkan Anda untuk menyusun sisa stack.
| Fitur | Jest | Mocha |
|---|---|---|
| Kompleksitas pengaturan | Rendah untuk tim kebanyakan | Tinggi karena biasanya Anda menambahkan library asertasi dan mocking |
| Asertasi | Terintegrasi | Sering digunakan bersama dengan library lain |
| Pengiriman palsu | Terintegrasi | Sering digunakan bersama dengan library lainnya |
| Pengujian Asinkron | Terintegrasi dan sederhana | Disedukung, tetapi tergantung lebih pada pengaturan sekitar |
| Alur Kerja Coverage | Sering diintegrasi ke dalam alat rantai yang sama | Sering lebih terpisah-pisah |
| Pilihan Terbaik | context: Halaman/Areas: Capgo Builder / produk halaman native cloud build. Peran: Label UI singkat atau item navigasi. Pesan kunci `native_build_builder_compare_fit_feature` (Native Build Builder Compare Fit Feature). | Proyek baru, tim yang ingin konsistensi |
Stack legacy, tim yang ingin kontrol modular Jika tim Anda harus bertanya-tanya mana perpustakaan asertasi dan perpustakaan mocking yang harus dipasangkan dengan runner, Anda mungkin ingin menggunakan Jest.
Rekomendasi saya untuk tim kebanyakan
Untuk proyek modern kebanyakan, saya akan memilih Jest kecuali kodebase sudah memiliki alasan kuat untuk tetap menggunakan Mocha. Saran ini semakin kuat ketika aplikasi mencakup Capacitor untuk Electronkarena proyek-proyek tersebut sudah memiliki bagian yang cukup bergerak. Mengurangi penyebaran alat uji membayar hasilnya dengan cepat.
Mocha masih relevan dalam layanan Node.js yang lebih tua atau kodebase yang sudah berumur karena ekosistem di sekitarnya sudah terjalin.
Tapi untuk insinyur mid-level yang mengatur suite yang kuat dari awal, Jest biasanya mengurangi gesekan daripada menciptakannya.
Perlu diingat satu hal penting. Cypress dan Playwright adalah alat-alat yang sangat baik, tapi mereka menyelesaikan masalah yang berbeda. Mereka lebih baik untuk pengujian browser-level dan end-to-end, bukan loop dalam yang cepat di mana pengujian unit JavaScript seharusnya berada.
A setup tes yang bersih haruslah membosankan. Jika menambahkan tes pertama terasa rumit, kemungkinan suite tidak akan tetap sehat.

Akonfigurasi Jest yang sederhana
Mulai dengan proyek JavaScript yang sudah memiliki package.json Kemudian tambahkan Jest sebagai dependensi pengembangan dan hubungkan skrip tes.
{
"scripts": {
"test": "jest"
}
}
Itu sudah cukup untuk banyak proyek. Anda dapat menambahkan konfigurasi lebih lanjut jika sistem modul, transpilasi, atau struktur monorepo memerlukan.
Jika Anda sedang membangun aplikasi Capacitor secara lokal dan ingin lingkungan pengembangan Anda dalam kondisi sebelum menambahkan tes di sekitar logika bersama, Capgo's guide untuk mengatur lingkungan lokal Capacitor Tulis tes sebelum __CAPGO_KEEP_0__
Write the test before the code
menulis tes pertama menulis tes sebelum __CAPGO_KEEP_0__dan mengatur ulang tes dengan describe dan it, dan mengatur ulang periksa sekitar expect(...) klaim dalam pedoman tes unit JavaScriptnya itu penting karena perubahan test-first mengubah cara Anda merancang __CAPGO_KEEP_0__..
That matters because test-first changes how you design code. Functions tend to become smaller, dependencies become more visible, and side effects stop leaking into logic that should stay pure.
Contoh minimal berikut:
// math.js
function addTax(amount, rate) {
return amount + amount * rate;
}
module.exports = { addTax };
// math.test.js
const { addTax } = require('./math');
describe('addTax', () => {
it('returns the amount with the tax applied', () => {
expect(addTax(100, 0.2)).toBe(120);
});
});
Pakai Arrange Act Assert setiap kali
Polanya Arrange, Act, Assert Polanya menjaga tes tetap dapat dibaca, bahkan ketika mereka tumbuh lebih kompleks.
- Arrange masukan dan setiap pengaturan yang dibutuhkan.
- Act melakukan
- Assert pada hasilnya.
Aplikasikan pada bantuan validasi:
function isSupportedPlatform(platform) {
return ['ios', 'android', 'web', 'desktop'].includes(platform);
}
describe('isSupportedPlatform', () => {
it('returns true for ios', () => {
// Arrange
const platform = 'ios';
// Act
const result = isSupportedPlatform(platform);
// Assert
expect(result).toBe(true);
});
});
Uji coba kecil bertahan lama. Sebuah uji coba biasanya harus menjawab satu pertanyaan, bukan menceritakan alur kerja seluruhnya.
Untuk Capacitor dan proyek Electron, disiplin itu lebih penting karena logika murni Anda sering kali berada di samping integrasi desktop atau native code. Pastikan aturan bisnis Anda dapat diuji tanpa runtime platform, dan uji coba pertama Anda tidak akan menjadi uji coba yang berguna terakhir.
Menguasai Mocks dan Asynchronous Code
Banyak bug di aplikasi code tidak berasal dari penjumlahan dua angka. Mereka berasal dari code yang mencapai luar dirinya sendiri: permintaan jaringan, file, API plugin, timer, saluran IPC, lapisan penyimpanan.
Itu di mana mocking membantu. Ini memberikan Anda kontrol atas batasannya sehingga uji coba dapat fokus pada keputusan code.

Batasi batasan, bukan semuanya
Panduan tes yang dapat dipertahankan menekankan Penggunaan coverage perilaku tunggal dan Satu asertasi kuat per tes, dan juga mengingatkan bahwa menggunakan mock yang berlebihan membuat tes menjadi rapuh dan terikat pada detail implementasi, seperti yang disingkatkan dalam artikel ini Artikel TestRail tentang tes unit yang dapat dipertahankan.
Peringatan itu sangat penting dalam JavaScript. Tim sering mulai dengan mengmock semua modul yang diimport dan akhirnya menguji apakah fungsi memanggil fungsi lain dalam urutan yang
Target yang buruk untuk tes yang berat mock:
- apakah fungsi bantuan A memanggil fungsi bantuan B
- apakah layanan C memanggil serializer D
- apakah fungsi privat internal berjalan dua kali
Target yang lebih baik:
- apakah fungsi yang dikembalikan
- apakah itu menangani ketergantungan yang gagal dengan benar
- apakah itu mengubah data menjadi bentuk yang diharapkan
Polanya yang lebih baik untuk Capacitor dan Electron code
Pada aplikasi mobile dan desktop, saya lebih suka layer penutup di sekitar API native atau platform. Kemudian unit test menggantikan layer penutup, bukan platform itu sendiri.
Struktur contoh:
// cameraGateway.js
async function getPhoto(cameraPlugin) {
return cameraPlugin.getPhoto();
}
module.exports = { getPhoto };
// profilePhotoService.js
async function loadProfilePhoto(cameraGateway) {
const photo = await cameraGateway.getPhoto();
return { path: photo.path, ready: true };
}
module.exports = { loadProfilePhoto };
// profilePhotoService.test.js
const { loadProfilePhoto } = require('./profilePhotoService');
test('returns mapped photo data', async () => {
const fakeCameraGateway = {
getPhoto: jest.fn().mockResolvedValue({ path: '/tmp/pic.jpg' })
};
const result = await loadProfilePhoto(fakeCameraGateway);
expect(result).toEqual({ path: '/tmp/pic.jpg', ready: true });
});
Polanya itu juga berlaku untuk Electron. Tutup ipcRenderer, akses file, atau integrasi shell di balik adapter tipis. Unit test mengenai layer layanan, bukan runtime secara langsung.
Untuk tim yang menguji logika rilis dan jalur pembaruan di Capacitor aplikasi, Capgo memiliki panduan relevan tentang menguji pembaruan OTA Capacitor dengan skenario mock.
Ringkasan singkat membantu jika tim Anda masih mengnormalisasi gaya tes async:
Tes aliran async tanpa flakiness
Pakai async/await dalam tes ketika code yang sedang diuji mengembalikan janji. Lebih jelas daripada pola callback yang berat dan lebih mudah untuk di-debug.
async function fetchProfile(api) {
const response = await api.getUser();
return response.name;
}
test('returns the user name from the API response', async () => {
const api = {
getUser: jest.fn().mockResolvedValue({ name: 'Ava' })
};
const result = await fetchProfile(api);
expect(result).toBe('Ava');
});
Juga tes jalur gagal:
test('throws when the API request fails', async () => {
const api = {
getUser: jest.fn().mockRejectedValue(new Error('network failed'))
};
await expect(fetchProfile(api)).rejects.toThrow('network failed');
});
Tes baik dan buruk. Di produksi, jalur buruk biasanya yang diingat oleh pengguna.
Strategi Lanjutan untuk Tes yang Kuat
Sebuah suite tes menjadi berguna ketika tetap berguna setelah code berubah. Itu lebih sulit daripada menulis pila tes yang berhasil.

Pakai pembagian tes sebagai anggaran
Satu panduan yang praktis merekomendasikan pembagian sebesar 70/20/10 di antara tes unit, tes integrasi, dan tes akhir-ke-akhiranbersama dengan unit tes yang memberikan feedback yang paling cepat dan gagal yang paling stabil. Panduan yang sama mengatakan bahwa suatu suite unit penuh harus selesai dalam kurang dari 10 detik, dan cek pre-commit harus tetap kurang dari 5 detik, menurut panduan tes ini OpenReplay.
guideline
For a Capacitor or Electron app, a healthy balance usually looks like this:
- Untuk sebuah aplikasi __CAPGO_KEEP_0__ atau Electron, keseimbangan yang sehat biasanya terlihat seperti ini: Unit tes
- untuk logika harga, aturan akses, serialisasi, kelayakan pembaruan, flag fitur, dan transformasi keadaan Tes integrasi untuk penyimpanan adapter, wrapper plugin, dan kontrak IPC
- Uji Coba Akhir-ke-Akhir untuk beberapa perjalanan kritis seperti login, alur pembelian, sinkronisasi, atau prompt pembaruan
Indeks Koverasi adalah senter, bukan sasaran
Laporan koverasi berguna ketika membantu Anda menemukan cabang yang belum diuji dalam logika penting. Mereka menjadi berbahaya ketika tim mengejar persentase koverasi untuk kepentingan sendiri.
Validator login dengan uji kasus tepat memberikan nilai lebih daripada file yang tercover penuh dengan asertasi trivial. Hal itu terutama benar untuk input-heavy code seperti formulir, parser, logika tanggal, dan pengecekan izin. Jika tim Anda memperketat kualitas seputar validasi UI berat, panduan ini tentang menguasai validasi formulir frontend adalah komplement yang baik untuk strategi pengujian tingkat unit.
Uji Coba perilaku bertahan dari refaktor
Suku pengujian yang dapat diandalkan harus memungkinkan Anda merakit internal tanpa menulis ulang setengah uji coba. Cara termudah untuk mencapai hal itu adalah dengan mengklaim perilaku yang dapat diamati bukannya detail implementasi.
Contoh penggunaan yang tahan lama:
- Kondisi batas seperti input kosong, nilai-nilai mirip null, jenis yang tidak valid, dan string yang terlalu besar
- Hasil domain seperti “ditolak kembali karena izin yang hilang”
- Transisi keadaan seperti “mengubah status update sebagai menunggu setelah metadata download diverifikasi”
Penggunaan kasus yang sering rusak:
- menginspeksi panggilan helper internal
- mengklaim metode privat yang berurutan
- menggagalkan setiap lapisan dalam rantai panggilan
Untuk tim aplikasi yang membangun proses rilis yang disiplin, Capgo’s artikel tentang jaminan kualitas aplikasi bermanfaat karena menghubungkan pekerjaan tes ke jalur pipa rilis yang lebih luas.
Menguji untuk CI, Capacitor, dan Aplikasi Electron
Tes yang hanya menjalankan pada satu mesin pengembang bukanlah jaring pengaman. Itu adalah kebiasaan lokal.
CI mengubah pekerjaan tes JavaScript menjadi infrastruktur tim. Setiap push, pull request, atau cabang rilis dapat menjalankan perintah yang sama dengan harapan yang sama. Konsistensi ini lebih penting lagi untuk Capacitor dan proyek Electron, di mana pergeseran lingkungan menyebabkan gagal yang halus.
Buat CI sebagai jalur eksekusi default
Setidaknya, CI Anda harus menginstal dependensi dan menjalankan suite unit pada setiap set perubahan. Simpan perintah identik dengan pengembangan lokal saat mungkin.
Aksi workflow dasar GitHub dapat sekecil ini:
name: test
on: [push, pull_request]
jobs:
unit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci
- run: npm test
Itu sudah cukup untuk menangkap import yang rusak, asertasi yang gagal, dan asumsi platform yang tidak sengaja sebelum mereka mendarat di utama.
Untuk tim mobile yang mengirimkan melalui pipa otomatis, Capgo memiliki panduan praktis untuk mengatur CI/CD untuk aplikasi Capacitor.
Menguji interaksi plugin Capacitor
Cara yang salah untuk menguji unit Capacitor code adalah dengan menarik plugin native secara langsung ke dalam setiap layanan. Itu akan mengkopi tes suite Anda ke jembatan platform.
Pola yang lebih baik adalah abstraksi tipis:
// deviceStorage.js
async function saveFile(filesystem, path, data) {
return filesystem.writeFile({ path, data });
}
module.exports = { saveFile };
// draftService.js
async function persistDraft(storage, draft) {
await storage.save('draft.json', JSON.stringify(draft));
return { saved: true };
}
module.exports = { persistDraft };
// draftService.test.js
const { persistDraft } = require('./draftService');
test('persists a serialized draft', async () => {
const storage = {
save: jest.fn().mockResolvedValue(undefined)
};
const result = await persistDraft(storage, { title: 'Hello' });
expect(result).toEqual({ saved: true });
});
Konsep yang sama berlaku pada akses kamera, prompt biometrik, registrasi token push, dan status jaringan. Tahan panggilan plugin di adapter. Uji logika aplikasi terhadap interface yang dikendalikan.
Pengujian Electron main renderer dan IPC code
Aplikasi Electron memiliki dua sambungan penting: proses utama code dan renderer process codeproses renderer __CAPGO_KEEP_0__
. Jangan kaburkan mereka dalam pengujian.
- Konfigurasi yang dapat diandalkan biasanya memisahkan: Pengujian unit renderer
- untuk model tampilan, keadaan, format, dan logika bisnis sisi UI untuk menu, operasi file, dan keputusan siklus aplikasi
- tes kontrak IPC untuk bentuk pesan dan tanggapan yang diharapkan
Contoh wrapper IPC:
// ipcGateway.js
function sendSettings(ipcRenderer, payload) {
ipcRenderer.send('settings:update', payload);
}
module.exports = { sendSettings };
// ipcGateway.test.js
const { sendSettings } = require('./ipcGateway');
test('sends settings update over ipc', () => {
const ipcRenderer = { send: jest.fn() };
sendSettings(ipcRenderer, { theme: 'dark' });
expect(ipcRenderer.send).toHaveBeenCalledWith('settings:update', { theme: 'dark' });
});
Jika Anda kemudian mengubah implementasi internal dari satu bantuan ke bantuan lain, tes ini masih berlaku karena memverifikasi perilaku yang penting. Itu standar yang Anda inginkan di desktop dan mobile code.
Faq yang Sering Ditanyakan Tentang Pengujian Unit JavaScript
Apa perbedaan antara pengujian unit integrasi dan E2E
A pengujian unit memeriksa satu bagian logika kecil secara isolasi. Sebuah pengujian integrasi memeriksa apakah beberapa komponen atau layanan bekerja bersama-sama dengan benar. tes akhir ke akhir menguji perjalanan pengguna melalui aplikasi yang berjalan.
Gunakan tes unit untuk memperoleh kepercayaan cepat dalam aturan bisnis. Gunakan tes integrasi untuk sambungan-sambungan seperti penyimpanan, pembungkus plugin, dan IPC. Gunakan tes E2E dengan sedikit untuk alur kerja yang akan sangat terganggu jika mereka rusak.
Apakah kita harus mencapai penutupan penuh
Tidak. Penutupan penuh dapat mendorong tim ke tes-tes yang tidak berharga.
Penggunaan penutupan berguna ketika itu menunjukkan risiko code yang belum pernah diuji. Tidak berguna ketika insinyur menambahkan asertasi dangkal hanya untuk memenuhi dashboard. Jika suite Anda sangat rapuh, penutupan yang lebih banyak tidak akan menyelamatkannya.
Bagaimana kita menambahkan tes ke basis kode yang sudah ada
Mulai dari tempat perubahan sudah terjadi. Jangan membuat tim beku dan mengumumkan perubahan besar dalam strategi tes.
Sebuah urutan yang praktis seperti ini:
- Perlindungi code yang aktif terlebih dahulu dengan menambahkan tes ke modul yang Anda sentuh selama pekerjaan fitur atau perbaikan bug
- Ekstrak logika yang murni agar file-file sulit diuji sehingga aturan bisnis dapat diuji tanpa kebisingan framework atau runtime
- Tambahkan pembungkus jahitan sekitar plugin-plugin native, klien jaringan, panggilan file sistem, dan IPC Electron
- Tolak pola-polan rapuh ketika memperkenalkan mock. Panduan dari praktik pengujian JavaScript terbaik terutama berguna di sini karena menyoroti masalah seringkali terlewatkan dari over-mocking dan tes yang rapuh yang mengikuti
Tujuan bukanlah kesempurnaan segera. Itu adalah perbaikan yang stabil di tempat-tempat di mana regresi menghabiskan tim paling banyak.
Jika tim Anda mengirimkan Capacitor atau apakah Anda ingin meningkatkan kinerja aplikasi Anda dengan memilih platform yang tepat untuk live update? aplikasi dan memerlukan proses rilis yang lebih bersih sekitar perubahan JavaScript, Capgo adalah salah satu pilihan untuk dilihat. Ini menyediakan pembaruan langsung untuk aplikasi CapacitorJS dan Electron, dengan kontrol rollout dan observabilitas, sehingga tim dapat memasangkan unit testing yang solid dengan jalur yang lebih aman untuk mengirimkan perubahan bundle web tanpa harus menunggu tinjauan toko untuk setiap perbaikan.