Lompat ke konten utama

Unit Tests JavaScript: Panduan Komprehensif 2026

Belajar unit tests javascript dengan panduan kami tahun 2026. Meliputi Jest, Mocha, pengaturan, mocking, CI, dan tips untuk Capacitor & aplikasi Electron.

Martin Donadieu

Martin Donadieu

Pengembang Konten

Unit Tests JavaScript: Panduan Komprehensif 2026

Saat ini, Anda mungkin berada di salah satu situasi. Entah proyek JavaScript Anda hampir tidak memiliki tes dan setiap refactor terasa berisiko, atau Anda sudah memiliki tes dan separuh di antaranya lambat, rapuh, dan sulit dipercaya.

Itu semakin parah pada Capacitor dan Aplikasi Electron Aplikasi-aplikasi. Suatu 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 dari dependensi palsu. Jika Anda mengujinya dengan cara yang benar, Anda akan mendapatkan feedback cepat pada logika yang rusak.

Unit test yang baik tidak dimulai dengan sintaks matcher yang cerdas. Ini dimulai dengan batasan yang disiplin: uji logika murni secara langsung, isolasi efek sampingan, dan hindari menulis tes yang menghancurkan ketika Anda mengubah nama fungsi internal.

Daftar Isi

Pemilihan Framework Pengujian JavaScript Anda

Proyek JavaScript profesional membutuhkan runner tes yang nyata. Skrip ad hoc dan pengecekan manual console tidak dapat berkembang ketika beberapa insinyur menyentuh kodebase yang sama. Anda membutuhkan penemuan tes, asserisi, penanganan async, mock, dan cara menjalankan semuanya secara konsisten dalam pengembangan lokal dan CI.

Guidance saat ini terus berkonvergensi pada beberapa pilihan mainstream yang kecil. Jest, Mocha, dan Jasmine sering kali dianggap sebagai framework utama, dengan Jest seringkali diidentifikasi karena struktur tes bawaan, asertasi, pemalsuan, dan dukungan async dalam satu paket, seperti yang ditunjukkan di Lab JavaScript Pluralsight untuk Pengujian.

Tabel perbandingan menampilkan framework pengujian JavaScript populer termasuk Jest, Mocha, Cypress, dan Playwright.

Mengapa sebuah framework tidak optional

Kesalahan pertama tim membuat adalah menganggap unit test sebagai kegiatan sampingan. Biasanya hal ini menyebabkan penamaan file tidak konsisten, asertasi kustom yang tidak diingat, dan bantuan yang hanya dipahami oleh satu orang.

Sebuah framework memberikan Anda bahasa bersama:

  • Struktur tes dengan describe dan test atau it
  • Asertasi dengan matcher yang dapat dibaca
  • Hooks untuk pengaturan dan penghapusan
  • Support Asinkron untuk janji dan timer
  • Alat Palsu untuk ketergantungan eksternal

Jika tim Anda juga membutuhkan pandangan yang lebih luas tentang otomatisasi tes di luar pekerjaan tingkat unit, Capgo memiliki gambaran yang berguna tentang pemantauan otomatis dalam alur pengiriman aplikasi.

Jest vs Mocha secara singkat

Jest dan Mocha mewakili dua filosofi yang berbeda.

Jest adalah pilihan semua dalam satu. Ia dilengkapi dengan sebagian besar yang tim butuhkan pada hari pertama.
Mocha lebih modular. Ini memberikan Anda runner dan mengharapkan Anda untuk menyusun bagian lain dari stack.

Fitur Jest Mocha
Kompleksitas pengaturan Lebih rendah untuk tim kebanyakan Tinggi karena biasanya Anda menambahkan library asertasi dan mocking
Asertasi Tersedia secara bawaan Biasanya dipasangkan dengan library lainnya
Mocking Dibangun dalam Biasanya dipasangkan dengan library lain
Pengujian async Dibangun dan sederhana Dapat didukung, tetapi tergantung lebih pada pengaturan sekitar
Alur kerja coverage Biasanya diintegrasi ke dalam rantai alat yang sama Seringkali lebih terpisah-pisah
Pilihan terbaik Proyek baru, tim yang ingin konsistensi Stack legacy, tim yang ingin kontrol modular

Aturan praktis: Jika tim Anda harus bertanya-tanya perpustakaan asertasi mana dan perpustakaan mock 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. Rekomendasi ini semakin kuat ketika aplikasi termasuk Capacitor atau Electron, karena proyek-proyek tersebut sudah memiliki cukup banyak bagian yang bergerak. Mengurangi penyebaran alat uji membayar cepat.

Mocha masih relevan dalam layanan Node.js yang lebih tua atau kodebase yang sudah lama, karena ekosistem di sekitarnya sudah terjalin dengan baik. Namun, untuk insinyur mid-level yang mengatur suite yang kuat dari awal, Jest biasanya mengurangi gesekan lebih banyak daripada yang dibuat.

Catatan penting tentang skop. Cypress dan Playwright adalah alat-alat yang sangat baik, tetapi mereka menyelesaikan masalah yang berbeda. Mereka lebih baik untuk pengujian browser-level dan end-to-end, bukan loop inner yang cepat di mana pengujian unit JavaScript seharusnya hidup.

Pengaturan Proyek dan Pengujian Pertama Anda

Suatu setup pengujian yang bersih haruslah membosankan. Jika menambahkan tes pertama terasa rumit, maka suite tersebut mungkin tidak akan tetap sehat.

Seorang pria berpakaian kacamata bekerja pada proyek pengembangan perangkat lunak di laptop di atas meja kayu.

Setup Jest yang sederhana

Mulai dengan proyek JavaScript yang sudah memiliki package.json. Kemudian tambahkan Jest sebagai dependensi pengembangan dan hubungkan skrip pengujian.

{
  "scripts": {
    "test": "jest"
  }
}

Itu sudah cukup untuk banyak proyek. Anda dapat menambahkan konfigurasi lebih lanjut jika sistem modul, transpilasi, atau struktur monorepo memerlukannya.

Jika Anda sedang membangun aplikasi Capacitor secara lokal dan ingin lingkungan pengembangan Anda dalam kondisi sebelum menambahkan tes sekitar logika bersama, panduan Capgo untuk mengatur lingkungan lokal Capacitor adalah mitra yang praktis.

Tulis tes sebelum code

Polanya pertama bukan hanya preferensi pribadi. Biro Perlindungan Konsumen Keuangan Amerika Serikat dalam panduan JavaScriptnya secara eksplisit merekomendasikan menulis tes terlebih dahuluMengorganisir tes dengan describe dan itMengatur cek sekitar expect(...) klaiman dalam panduan tes unit JavaScriptnya Karena itu penting karena tes pertama 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:

// 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 menjadi lebih kompleks.

  1. Arrange the input dan setup yang dibutuhkan.
  2. Act dengan memanggil fungsi.
  3. Assert terhadap hasilnya.

Diterapkan pada helper 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 yang lengkap.

Untuk Capacitor dan proyek Electron, disiplin itu lebih penting karena logika murni Anda sering kali berada di samping integrasi native atau desktop code. Pastikan aturan bisnis tetap 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 bilangan. Mereka berasal dari code yang mencapai luar diri: permintaan jaringan, file, API plugin, timer, saluran IPC, lapisan penyimpanan.

Itu di mana mocking membantu. Ini memberi Anda kontrol atas batasannya sehingga uji coba dapat fokus pada keputusan code.

Diagram papan putih yang menggambarkan arsitektur mikro layanan dengan API, penyimpanan data, layanan eksternal, dan aliran data berbasis acara.

Batasan palsu, bukan semuanya

Pedoman tes yang dapat dipelihara menekankan penutupan perilaku tunggal dan asertasi kuat satu per tes, dan juga mengingatkan bahwa menggunakan palsu berlebihan membuat tes rapuh dan terikat pada detail implementasi, seperti yang disingkapkan dalam artikel TestRail tentang tes unit yang dapat dipelihara.

Pesan itu sangat penting dalam JavaScript. Tim sering mulai dengan menggantikan semua modul yang diimport dan akhirnya menguji apakah fungsi memanggil fungsi lain dalam urutan yang "benar", bukan menguji perilaku nyata.

Target palsu yang buruk:

  • apakah fungsi B helper dipanggil oleh fungsi A helper
  • apakah fungsi D serializer dipanggil oleh fungsi C service
  • apakah fungsi privat internal berjalan dua kali

Target yang lebih baik:

  • apa yang dikembalikan oleh fungsi
  • apakah mengatasi ketergantungan yang gagal dengan benar
  • apakah mengubah data menjadi bentuk yang diharapkan

Polanya yang lebih baik untuk Capacitor dan Electron code

Pada aplikasi mobile dan desktop, saya lebih suka lapisan wrapper di sekitar API native atau platform. Kemudian, unit test menggantikan wrapper, 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 Capacitor pembaruan OTA dengan skenario mock.

Ringkasan singkat membantu jika tim Anda masih normalisasi gaya tes async:

Menguji arus async tanpa kegagalan

Gunakan async/await dalam pengujian ketika code yang diuji kembali sebuah promise. 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 uji 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');
});

Uji baik jalur yang bahagia dan jalur yang tidak enak. Di produksi, jalur yang tidak enak biasanya adalah yang pengguna ingat.

Strategi Lanjutan untuk Pengujian yang Kuat

Sebuah suite pengujian menjadi berguna ketika tetap berguna setelah code berubah. Itu lebih sulit daripada menulis sebuah tumpukan pengujian yang berhasil.

Diagram yang menggambarkan strategi untuk membangun perangkat lunak yang kuat melalui pengujian yang komprehensif dan suite pengujian yang dapat dipelihara.

Gunakan pembagian pengujian sebagai anggaran

Satu panduan praktis merekomendasikan 70/20/10 pembagian sebesar across pengujian unit, pengujian integrasi, dan pengujian akhir-ke-akhirbersama dengan unit test yang memberikan feedback yang paling cepat dan kegagalan yang paling stabil. Panduan yang sama mengatakan bahwa suite unit penuh seharusnya selesai dalam kurang dari 10 detik, dan periksa pre-commit harus tetap kurang dari 5 detik, menurut panduan pengujian OpenReplay ini Saya menganggap itu sebagai alat anggaran, bukan agama. Jika sebagian besar upaya Anda masuk ke dalam pengujian end-to-end, tim Anda akan menunggu terlalu lama untuk mendapatkan feedback. Jika semuanya hanya unit-only, Anda akan kehilangan batasan sistem nyata..

Untuk aplikasi __CAPGO_KEEP_0__ atau Electron, keseimbangan yang sehat biasanya terlihat seperti ini:

For a Capacitor or Electron app, a healthy balance usually looks like this:

  • untuk logika harga, aturan akses, pengaturan serialisasi, kelayakan pembaruan, flag fitur, dan transformasi keadaan Pengujian integrasi
  • untuk adapter penyimpanan, pembungkus plugin, dan kontrak IPC bersama dengan unit test yang memberikan feedback yang paling cepat dan kegagalan yang paling stabil. Panduan yang sama mengatakan bahwa suite unit penuh seharusnya selesai dalam kurang dari 10 detik, dan periksa pre-commit harus tetap kurang dari 5 detik, menurut panduan pengujian OpenReplay ini Saya menganggap itu sebagai alat anggaran, bukan agama. Jika sebagian besar upaya Anda masuk ke dalam pengujian end-to-end, tim Anda akan menunggu terlalu lama untuk mendapatkan feedback. Jika semuanya hanya unit-only, Anda akan kehilangan batasan sistem nyata. Untuk aplikasi __CAPGO_KEEP_0__ atau Electron, keseimbangan yang sehat biasanya terlihat seperti ini: Pengujian unit untuk logika harga, aturan akses, pengaturan serialisasi, kelayakan pembaruan, flag fitur, dan transformasi keadaan Pengujian integrasi untuk adapter penyimpanan, pembungkus plugin, dan kontrak IPC
  • Uji Akhir-akhir untuk beberapa perjalanan kritikal seperti login, alur pembelian, sinkron, atau peringatan pembaruan

Koverasi adalah senter, bukan target

Laporan koverasi berguna ketika membantu Anda menemukan cabang yang belum diuji di 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 periksa izin. Jika tim Anda memperketat kualitas di sekitar validasi UI berat, panduan ini tentang menguasai validasi formulir frontend merupakan tambahan yang baik untuk strategi pengujian tingkat unit.

Pengujian perilaku yang bertahan lama

Saat Anda melakukan refactor internal, suatu suite yang dapat diandalkan harus memungkinkan Anda melakukan refaktor tanpa menulis ulang setengah dari pengujian. Cara termudah untuk mencapai hal itu adalah dengan mengasumsikan perilaku yang dapat diamati bukan detail implementasi.

Penggunaan yang dapat bertahan lama:

  • Kondisi batas seperti input kosong, nilai-nilai mirip null, jenis yang tidak valid, dan string yang terlalu besar
  • Hasil domain seperti “pengembalian ditolak karena kekurangan izin”
  • Transisi keadaan seperti “mengupdate sebagai menunggu setelah metadata diunduh diverifikasi”

Penggunaan kasus yang sering rusak:

  • menginspeksi panggilan helper internal
  • mengklaim urutan metode privat
  • menggagalkan setiap lapisan dalam rantai panggilan

Untuk tim aplikasi yang membangun proses rilis yang disiplin, artikel Capgo tentang penjaminan kualitas aplikasi adalah berguna karena menghubungkan pekerjaan tes ke jalur pipa rilis yang lebih luas.

Testing untuk CI, Capacitor, dan Aplikasi Electron

Tes yang hanya berjalan di satu mesin pengembang bukanlah jaringan keamanan. Itu adalah kebiasaan lokal.

CI mengubah tes unit kerja JavaScript menjadi infrastruktur tim. Setiap push, pull request, atau cabang rilis dapat menjalankan perintah yang sama dengan harapan yang sama. Konsistensi itu lebih penting lagi untuk Capacitor dan proyek Electron, di mana pergeseran lingkungan menyebabkan gagal yang halus.

Buat CI sebagai jalur eksekusi default

Paling tidak, CI Anda harus menginstal dependensi dan menjalankan suite unit pada setiap set perubahan. Pastikan perintahnya sama dengan pengembangan lokal saat mungkin.

Contoh workflow GitHub Actions yang sederhana bisa 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, asseri 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. Ini akan mengkopi tes suite Anda ke jembatan platform.

Polanya 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 });
});

Ide yang sama berlaku untuk akses kamera, prompt biometrik, registrasi token push, dan status jaringan. Simpan panggilan plugin di adapter. Uji logika aplikasi terhadap interface yang dikontrol.

Uji Electron main renderer dan IPC code

Aplikasi Electron memiliki dua celah penting: proses utama code dan proses renderer code. Jangan kaburkan mereka dalam uji.

Konfigurasi yang dapat diandalkan biasanya memisahkan:

  • Uji unit proses renderer untuk model tampilan, keadaan, format, dan logika bisnis sisi UI
  • Uji unit proses utama untuk menu, operasi file, dan keputusan siklus aplikasi
  • tes kontrak IPC untuk bentuk pesan dan respons 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.

Tanya-Tanya Sering Ditanyakan Tentang Unit Testing JavaScript

Apa perbedaan antara unit integration dan E2E tests

A unit test menguji satu bagian logika kecil secara isolasi. Sebuah integration test menguji apakah beberapa komponen atau layanan bekerja bersama-sama dengan benar. Sebuah tes akhir ke akhir Melakukan tes akhir ke akhir untuk menguji perjalanan pengguna melalui aplikasi yang berjalan.

Pakai tes unit untuk mendapatkan kepercayaan cepat dalam aturan bisnis. Pakai tes integrasi untuk sambungan-sambungan seperti penyimpanan, wrapper plugin, dan IPC. Pakai tes E2E dengan sedikit untuk alur kerja yang akan sangat terganggu jika mereka rusak.

Apakah kita harus mencapai coverase penuh

Tidak. Coverase penuh dapat mendorong tim ke tes-tes yang tidak berharga.

Coverase berguna ketika menunjukkan risiko code yang belum pernah diuji. Tidak berguna ketika insinyur menambahkan asertasi dangkal hanya untuk memenuhi dashboard. Jika suite tes Anda sangat rapuh, coverase penuh 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:

  • Pertahankan code yang aktif terlebih dahulu Dengan menambahkan tes ke modul yang Anda sentuh selama pekerjaan fitur atau perbaikan bug
  • Ekstrak logika yang murni dari file yang sulit diuji sehingga aturan bisnis dapat diuji tanpa kebisingan kerangka atau waktu eksekusi
  • Tambahkan wrapper jahitan sekitar plugin native, klien jaringan, panggilan filesystem, dan IPC Electron
  • Tolak pola yang rapuh ketika memperkenalkan mock. Panduan dari praktik terbaik pengujian JavaScript terutama berguna di sini karena menyoroti masalah yang sering terlewatkan yaitu 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 Electron Aplikasi dan kebutuhan memerlukan proses rilis yang lebih bersih seputar perubahan JavaScript, Capgo adalah salah satu pilihan untuk dilihat. Ini menyediakan pembaruan waktu nyata 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.

Live update untuk aplikasi Capacitor

Ketika bug layer web masih hidup, kirimkan perbaikan melalui Capgo bukan menunggu hari-hari untuk persetujuan toko aplikasi. Pengguna mendapatkan update di latar belakang sementara perubahan native tetap dalam jalur review normal.

Mulai Sekarang

Terbaru dari Blog Kami

Capgo memberikan Anda wawasan terbaik yang Anda butuhkan untuk menciptakan aplikasi mobile yang benar-benar profesional.