Lompat ke konten utama

Unit Tests JavaScript: Panduan Komprehensif 2026

Belajar unit tests javascript dengan panduan kami 2026. Meliputi Jest, Mocha, pengaturan, pemalsuan, 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 berikut. 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.

Masalah ini semakin parah di Capacitor dan aplikasi Electron. Fitur sederhana dapat menyentuh logika bisnis bersama, API browser, plugin native, file lokal, IPC, dan layanan remote dalam aliran yang sama. Jika Anda menguji bagian-bagian tersebut dengan cara yang salah, suite Anda menjadi labirin dependensi palsu. Jika Anda mengujinya dengan cara yang benar, Anda mendapatkan feedback cepat pada logika yang rusak. Martin Donadieu

Unit tes JavaScript bekerja tidak dimulai dengan sintaks matcher yang cerdas. Ini dimulai dengan batasan yang disiplin: tes logika murni secara langsung, isolasi efek samping, dan hindari menulis tes yang runtuh ketika Anda mengubah nama fungsi internal.

Daftar Isi

Memilih Framework Pengujian JavaScript Anda

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

Pedoman saat ini terus berkonvergensi pada beberapa pilihan mainstream yang kecil. Jest, Mocha, dan Jasmine seringkali dianggap sebagai framework utama, dengan Jest seringkali dianggap sebagai pilihan utama karena struktur tes bawaan, asertasi, mocking, dan dukungan async dalam satu paket, seperti yang ditunjukkan dalam laboratorium pengujian JavaScript Pluralsight Tabel perbandingan yang menampilkan framework pengujian JavaScript populer termasuk Jest, Mocha, Cypress, dan Playwright.

Mengapa framework bukanlah pilihan opsional

__CAPGO_KEEP_0__

The first mistake teams make is treating unit tests as a side activity. Biasanya hal ini menyebabkan penamaan file tidak konsisten, asseri yang tidak pernah diingat, dan helper yang hanya dipahami oleh satu orang.

A framework memberikan Anda bahasa yang sama:

  • Struktur Test dengan describe dan test atau it
  • Asertasi dengan matcher yang mudah dibaca
  • Gagang untuk setup dan teardown
  • Dukungan Asinkron untuk promise dan timer
  • Alat-alat Mocking untuk dependensi luar

Jika tim Anda juga membutuhkan pandangan yang lebih luas tentang otomatisasi tes di luar pekerjaan tingkat unit, Capgo memiliki gambaran umum 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 adalah lebih modular. Ini memberikan Anda runner dan mengharapkan Anda untuk menyusun sisa stack.

Fitur Jest Mocha
Kompleksitas pengaturan Lebih rendah untuk tim kebanyakan Lebih tinggi karena biasanya Anda menambahkan library asertasi dan mocking
Asertasi Dibangun dalam Biasanya dipasangkan dengan library lain
Mocking Dibangun dalam Biasanya dipasangkan dengan library lain
Pengujian async Dibangun dalam dan sederhana Dukungan, tetapi lebih bergantung 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 Pangkalan lama, tim yang ingin kontrol modular

Aturan praktis: Jika tim Anda harus bertanya mana perpustakaan asertasi dan perpustakaan mocking yang harus dipasangkan dengan runner, Anda mungkin ingin menggunakan Jest.

Rekomendasi saya untuk tim yang paling umum

Untuk proyek modern yang paling banyak, saya akan memilih Jest kecuali kodebasis sudah memiliki alasan kuat untuk tetap menggunakan Mocha. Saran tersebut semakin kuat ketika aplikasi termasuk Capacitor atau Electron, karena proyek-proyek tersebut sudah memiliki cukup bagian yang bergerak. Mengurangi penyebaran alat uji membayar cepat.

Mocha masih relevan dalam layanan Node.js yang lebih tua atau kodebasis yang sudah berumur karena ekosistem di sekitarnya sudah terjalin. Tapi untuk seorang insinyur menengah yang mengatur suite yang kuat dari awal, Jest biasanya mengurangi gesekan lebih banyak daripada yang dibuat.

Catatan penting tentang ruang lingkup. Cypress dan Playwright adalah alat-alat yang sangat baik, tapi mereka menyelesaikan masalah yang berbeda. Mereka lebih baik untuk pemeriksaan browser-level dan end-to-end, bukan loop inner yang cepat di mana unit test JavaScript harus hidup.

Pengaturan Proyek dan Ujian Pertama

Suatu setup ujian yang bersih haruslah membosankan. Jika menambahkan ujian pertama terasa rumit, maka suite tidak akan tetap sehat.

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

Pengaturan Jest yang Sederhana

Mulai dengan proyek JavaScript yang sudah memiliki package.jsonTambahkan 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 memerlukan.

Jika Anda sedang membangun aplikasi Capacitor secara lokal dan ingin lingkungan pengembangan Anda dalam kondisi sebelum menambahkan pengujian di sekitar logika bersama, Capgo's panduan untuk mengatur lingkungan lokal Capacitor adalah mitra yang sangat berguna.

Tulis pengujian sebelum code

Gaya pengujian pertama bukan hanya preferensi pribadi. Badan Perlindungan Konsumen Keuangan Amerika Serikat secara eksplisit merekomendasikan menulis pengujian pertamamengorganisir pengujian dengan describe dan itdan membuat periksaan sekitar expect(...) klaim dalam dokumennya Pedoman pengujian unit JavaScript.

Hal ini penting karena pengujian terlebih dahulu mengubah cara Anda merancang code. Fungsi cenderung menjadi lebih kecil, dependensi menjadi lebih terlihat, dan efek sampingan berhenti mengalir ke logika yang seharusnya tetap murni.

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

Gunakan Arrange Act Assert setiap kali

The Polanya Arrange, Act, Assert menjaga agar tes tetap dapat dibaca, bahkan ketika mereka menjadi lebih kompleks. Siapkan

  1. Masukkan input dan setup yang diperlukan. Tindakan
  2. Panggil fungsi. Konfirmasi
  3. Panggilan On 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 kecil bertahan lama. Sebuah uji 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 native atau desktop code. Jaga aturan bisnis tetap dapat diuji tanpa runtime platform, dan uji pertama Anda tidak akan menjadi uji terakhir yang berguna.

Menguasai Mocks dan Asynchronous Code

Banyak bug di aplikasi code tidak berasal dari menambahkan 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 memberi Anda kontrol atas batasannya sehingga uji dapat fokus pada keputusan code.

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

Mock batasan, bukan segalanya

Panduan uji yang dapat dipertahankan menekankan penutupan perilaku tunggal dan Satu asseri kuat per tes, dan juga mengingatkan bahwa menggunakan mock yang berlebihan membuat tes menjadi rapuh dan terikat pada detail implementasi, seperti yang disinggung dalam artikel TestRail tentang tes unit yang dapat dipertahankan Artikel TestRail tentang tes unit yang dapat dipertahankan.

Peringatan itu sangat penting di JavaScript. Banyak tim mulai dengan mengmock semua modul yang diimport dan akhirnya menguji apakah fungsi memanggil fungsi lain dalam urutan yang

Sasaran buruk untuk tes yang berat mock:

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

Sasaran yang lebih baik:

  • apakah fungsi mengembalikan nilai yang diharapkan
  • apakah fungsi dapat menangani ketergantungan yang gagal dengan benar
  • apakah fungsi mengubah data menjadi bentuk yang diharapkan

Pola yang lebih baik untuk Capacitor dan Electron code

Dalam aplikasi mobile dan desktop, saya lebih suka layer penutup di sekitar API native atau platform. Kemudian, unit tests memalsukan 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 berfungsi juga untuk Electron. Tutup ipcRenderer, akses file, atau integrasi shell di balik adapter tipis. Unit tests menghantam 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 palsu.

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

Menguji aliran async tanpa flakiness

Gunakan async/await dalam tes ketika code yang diuji kembali janji. Lebih jelas daripada pola yang berat callback dan lebih mudah untuk 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 coba baik jalur bahagia maupun jalur yang tidak enak. Pada produksi, jalur yang tidak enak biasanya adalah yang yang diingat oleh pengguna.

Strategi Lanjutan untuk Tes yang Kuat

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

Diagram yang menggambarkan strategi untuk membangun perangkat lunak yang kuat melalui tes yang komprehensif dan suite tes yang dapat dirawat.

Gunakan pembagian tes sebagai anggaran

Satu panduan praktis merekomendasikan sebuah 70/20/10 pembagian di acrossunit, integrasi, dan tes akhir-ke-akhiran , dengan tes unit memberikan feedback yang paling cepat dan gagal yang paling stabil. Panduan yang sama mengatakan bahwa suite tes unit yang lengkap seharusnya selesai dalamkurang dari 10 detik , dan periksa pre-commit seharusnya tetap dalamMenurut saya Petunjuk uji OpenReplay.

Saya menganggap itu sebagai alat pengaturan anggaran, bukan agama. Jika sebagian besar upaya Anda masuk ke dalam uji akhir ke akhir, tim Anda akan menunggu terlalu lama untuk mendapatkan feedback. Jika semua itu hanya uji unit, Anda akan melewatkan batasan sistem yang sebenarnya.

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

  • Uji unit untuk logika harga, aturan akses, pengaturan serialisasi, kelayakan pembaruan, flag fitur, dan transformasi keadaan
  • Uji integrasi untuk adapter penyimpanan, pembungkus plugin, dan kontrak IPC
  • Uji E2E untuk beberapa perjalanan kritikal seperti login, alur pembelian, sinkronisasi, atau prompt pembaruan

Pemantauan coverage adalah senter, bukan target

Laporan coverage berguna ketika membantu Anda menemukan cabang yang belum diuji di logika penting. Mereka menjadi berbahaya ketika tim mengejar persentase coverage untuk kepentingan sendiri.

A validator login dengan uji kasus sampingan yang berpikiran memberikan nilai lebih dari sebuah file yang penuh dengan asertasi-asertasi sederhana. Hal itu terutama benar untuk input-heavy code seperti formulir, parser, logika tanggal, dan periksa izin. Jika tim Anda sedang memperketat kualitas di sekitar validasi UI yang berat, panduan ini tentang menguasai validasi formulir frontend adalah komplement yang baik untuk strategi pengujian tingkat unit.

Uji perilaku yang bertahan dari refaktor

Sebuah suite yang dapat diandalkan harus memungkinkan Anda merakit internal tanpa menulis ulang setengah uji. Cara termudah untuk mencapai itu adalah dengan mengklaim perilaku yang dapat diamati bukan detail implementasi.

Kasus penggunaan yang tetap kuat:

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

Kasus penggunaan yang sering rusak:

  • menginspeksi panggilan helper internal
  • menegaskan urutan metode privat
  • menggunakan mock untuk setiap lapisan dalam rantai panggilan

Untuk tim aplikasi yang membangun proses rilis yang disiplin, artikel Capgo tentang jaminan kualitas aplikasi bermanfaat karena menghubungkan pekerjaan tes dengan pipa rilis yang lebih luas.

Menguji untuk CI, Capacitor, dan Aplikasi Electron

Jika hanya satu mesin pengembang yang menjalankan tes, itu bukanlah jaring pengaman. Itu hanya kebiasaan lokal.

CI mengubah tes unit ke infrastruktur tim. Setiap push, pull request, atau cabang rilis dapat menjalankan perintah yang sama dengan harapan yang sama. Konsistensi itu sangat penting terutama untuk Capacitor dan projek Electron, di mana pergeseran lingkungan menyebabkan gagal yang halus.

Ubah CI menjadi jalur eksekusi default

Paling tidak, CI Anda harus menginstal dependensi dan menjalankan suite unit pada setiap perubahan. Simpan perintah identik dengan pengembangan lokal saat mungkin.

Alur kerja dasar GitHub Actions 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

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. Hal ini akan mengkopi suite uji 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 });
});

Pemikiran yang sama berlaku untuk akses kamera, prompt biometrik, pendaftaran token push, dan status jaringan. Simpan panggilan plugin di adapter. Uji logika aplikasi terhadap interface yang Anda kendalikan.

Menguji Electron main renderer dan IPC code

Aplikasi Electron memiliki dua sambungan penting: main renderer dan IPC. proses utama code dan proses renderer code. Jangan memudahkan mereka dalam tes.

Konfigurasi yang dapat diandalkan biasanya memisahkan:

  • Uji unit proses renderer untuk model tampilan, keadaan, pengaturan format, dan logika bisnis sisi UI
  • Uji unit proses utama untuk menu, operasi file, dan keputusan siklus aplikasi
  • Uji 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' });
});

If 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.

Pertanyaan Tertulis yang Sering Ditanyakan Tentang Pengujian Satuan JavaScript

Apa perbedaan antara pengujian satuan, integrasi, dan E2E

A pengujian satuan menguji satu bagian logika kecil secara isolasi. Sebuah pengujian integrasi menguji apakah beberapa komponen atau layanan bekerja bersama-sama dengan benar. Sebuah pengujian E2E menguji perjalanan pengguna melalui aplikasi yang berjalan.

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

Apakah kita harus berusaha mencapai penutupan penuh?

No. Pemahaman penuh dapat mendorong tim ke tes yang tidak berharga.

Pemahaman berguna ketika itu mengekspos risiko code yang belum pernah diuji. Tidak berguna ketika insinyur menambahkan asertasi dangkal hanya untuk memuaskan dashboard. Jika suite Anda rapuh, pemahaman 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 pada strategi tes.

Sebuah urutan yang praktis seperti ini:

  • Terlebih dahulu lindungi code yang aktif Dengan menambahkan tes ke modul yang Anda sentuh selama pekerjaan fitur atau perbaikan bug
  • Ekstrak logika murni Dari file yang sulit diuji sehingga aturan bisnis dapat diuji tanpa kebisingan framework atau runtime
  • Tambahkan wrapper celah Seputar 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 keterpaduan segera. Itu adalah perbaikan yang stabil di tempat-tempat di mana regresi menghabiskan biaya tim paling banyak


Jika tim Anda mengirimkan Capacitor atau aplikasi Electron dan perlu proses rilis yang lebih bersih seputar perubahan JavaScript, __CAPGO_KEEP_0__ Capgo Ditulis oleh

Pembaruan Langsung untuk Capacitor Apps

Ketika bug layer web masih aktif, kirimkan perbaikan melalui Capgo bukan menunggu hari-hari untuk persetujuan toko aplikasi. Pengguna mendapatkan pembaruan 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 membuat aplikasi mobile profesional yang sebenarnya.