Lompat ke Konten Utama

Panduan Komprehensif Unit Tests JavaScript 2026

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

Unit Tests JavaScript: Panduan Komprehensif 2026

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 separuh dari mereka lambat, rapuh, dan sulit dipercaya.

Yang semakin parah di Capacitor dan Electron Aplikasi. 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.

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

Isi Kandungan

Memilih Framework Pengujian JavaScript

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

Guida saat ini terus berkonvergensi pada beberapa pilihan mainstream. Jest, Mocha, dan Jasmine seringkali dianggap sebagai framework utama, dengan Jest Dapat seringkali diidentifikasi karena struktur uji bawaan, asertasi, pemalsuan, dan dukungan async dalam satu paket, seperti yang ditunjukkan di sini Lab Pemrograman JavaScript untuk Pengujian.

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

Mengapa sebuah framework tidak boleh diabaikan

The first mistake teams make is treating unit tests as a side activity. That usually leads to inconsistent file naming, custom assertions nobody remembers, and helpers that only one person understands.

Apa itu framework memberikan bahasa umum yang sama:

  • Struktur tes dengan describe atau test Klaim it
  • Assertions dengan matcher yang dapat dibaca
  • Hooks Dukungan asinkron
  • untuk promise dan timer untuk promise dan timer
  • Alat Palsu untuk dependensi eksternal

If your team also needs a broader view of test automation beyond unit-level work, Capgo has a useful overview of pengujian otomatis dalam alur kerja pengiriman aplikasi.

Jest vs Mocha secara singkat

Jest dan Mocha mewakili dua filosofi yang berbeda.

Jest adalah pilihan yang lengkap. 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 Setup Lebih rendah untuk tim kebanyakan Lebih tinggi karena biasanya Anda menambahkan perpustakaan asertasi dan mocking
Asertasi Dibangun dalam Biasanya dipasangkan dengan perpustakaan lain
Mocking Dibangun dalam Biasanya dipasangkan dengan perpustakaan lain
Pengujian Asinkron Tersedia secara bawaan dan sederhana Dukungan ada, tetapi tergantung lebih pada pengaturan sekitar
Alur Pelacakan Coverage Dapat diintegrasi ke dalam alat rantai yang sama Banyaknya bagian yang terpisah
Pilihan Terbaik Proyek Baru, Tim yang Menginginkan Konsistensi Stack Legacy, Tim yang Menginginkan Kontrol Modul

Aturan Praktis: Jika tim Anda harus bertanya-tanya perpustakaan asertasi dan perpustakaan mocking mana yang harus dipasangkan dengan runner, kemungkinan besar Anda ingin menggunakan Jest.

Rekomendasi yang Saya Berikan untuk Tim yang Banyak

For most modern projects, I’d choose Jest kecuali kodebase sudah memiliki alasan kuat untuk tetap menggunakan Mocha. Rekomendasi ini semakin kuat ketika aplikasi termasuk Capacitor atau ElectronKarena proyek-proyek tersebut sudah memiliki komponen yang cukup banyak. Mengurangi kelebihan alat pengujian memberikan hasil yang cepat.

Mocha still makes sense in older Node.js services or long-lived codebases where the ecosystem around it is already settled. But for a mid-level engineer setting up a robust suite from scratch, Jest usually removes more friction than it creates.

One important scope note. Cypress and Playwright are excellent tools, but they solve a different problem. They’re better for browser-level and end-to-end checks, not the fast inner loop where unit tests JavaScript work should live.

Pengaturan Proyek dan Ujian Pertama

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

Orang pria berpakaian sederhana bekerja pada proyek pengembangan perangkat lunak di atas meja kayu dengan laptop.

Pengaturan Jest Sederhana

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

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

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

Jika Anda sedang membangun aplikasi Capacitor secara lokal dan ingin lingkungan pengembangan Anda terorganisir sebelum menambahkan tes di sekitar logika bersama, Capgo's guide untuk mengatur lingkungan lokal Capacitor Tulislah tes sebelum __CAPGO_KEEP_0__

Tulislah tes sebelum code

Pola tes pertama bukan hanya preferensi pribadi. Pedoman JavaScript dari Badan Perlindungan Konsumen Keuangan Amerika Serikat secara eksplisit merekomendasikan , mengorganisir tes denganMengorganisir tes dengan describe and itklaim dalam panduan pengujian unit JavaScriptnya expect(...) asertasi dalam itu Panduan Pengujian Unit JavaScript.

Karena itu, pengujian pertama mengubah cara Anda merancang code. Fungsi cenderung menjadi lebih kecil, ketergantungan 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);
  });
});

Pakai Arrange Act Assert setiap kali

Gaya Gaya Arrange, Act, Assert Polanya menjaga tes tetap mudah dibaca, bahkan ketika mereka semakin kompleks.

  1. Siapkan Siapkan masukan dan setiap setup yang dibutuhkan.
  2. Jalankan Jalankan fungsi dengan memanggilnya.
  3. Periksa Periksa hasilnya.

Diaplikasikan 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 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 dapat diuji tanpa runtime platform, dan uji coba pertama Anda tidak akan menjadi uji coba yang berguna terakhir.

Menguasai Mocks dan Asinkron 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 adalah tempat di mana mocking membantu. Ini memberikan Anda kontrol atas batasan sehingga uji coba dapat fokus pada keputusan code.

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

Mock batasan, bukan segalanya

Panduan uji coba yang dapat dipelihara menekankan pemutusan koverage perilaku tunggal dan pernyataan kuat tunggal per uji cobadan juga mengingatkan bahwa menggunakan mock yang berlebihan membuat tes menjadi rapuh dan terikat pada detail implementasi, seperti yang disingkatkan dalam ini artikel TestRail tentang tes unit yang dapat dipelihara.

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

Tujuan yang buruk untuk tes yang berat mock:

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

Tujuan 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

Polanya yang lebih baik untuk Capacitor dan Electron code

In aplikasi mobile dan desktop, saya lebih suka menggunakan lapisan wrapper di sekitar API native atau platform. Kemudian, unit test mengimiti lapisan 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 juga berlaku untuk Electron. Wrap ipcRendererfile akses, 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 aplikasi Capacitor, Capgo memiliki panduan relevan tentang menguji pembaruan OTA Capacitor dengan skenario mock.

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

Menguji aliran async tanpa flakiness

Pakai async/await dalam tes ketika code yang diuji kembali janji. Lebih jelas daripada pola callback berat 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 yang sukses maupun jalur yang tidak. Pada produksi, jalur yang tidak biasanya adalah yang pengguna ingat.

Strategi Lanjutan untuk Tes yang Kuat

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

Diagram yang menggambarkan strategi untuk membuat perangkat lunak yang kuat melalui penutupan tes yang komprehensif dan suite tes yang dapat dipelihara.

Pakai split tes sebagai anggaran

Salah satu panduan praktis merekomendasikan 70/20/10 split di antara tes unit, integrasi, dan tes akhir-ke-akhiranDengan unit test yang memberikan feedback paling cepat dan gagal yang paling stabil. Panduan yang sama menyatakan bahwa suatu suite unit yang lengkap seharusnya selesai dalam kurang dari 10 detik, dan cek pre-commit seharusnya tetap kurang dari 5 detik, according to this Petunjuk Penguji Replikasi Terbuka.

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

Untuk aplikasi Capacitor 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
  • Pengujian E2E untuk beberapa perjalanan kritikal seperti login, alur pembelian, sinkronisasi, atau permintaan pembaruan

Pengukuran koverasi adalah senter, bukan target

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 pengujian kasus tepat memberikan nilai lebih daripada file yang terlapisi penuh dengan asertasi trivial. Hal itu terutama benar untuk input-heavy code seperti formulir, parser, logika tanggal, dan periksa akses. Jika tim Anda memperketat kualitas di sekitar UI yang berat pada validasi, panduan ini pada Belajar Validasi Form di Frontend adalah komplement yang baik untuk strategi pengujian tingkat unit.

Pengujian perilaku bertahan dari refactor

Sebuah suite yang dapat diandalkan harus memungkinkan Anda merubah bagian dalam tanpa harus menulis ulang setengah dari tes. Cara termudah untuk mencapai itu adalah dengan mengasumsikan perilaku yang dapat dilihat bukan detail implementasi.

Penggunaan yang dapat bertahan baik:

  • Pengujian batas Nilai input kosong, nilai null, jenis data tidak valid, dan string yang terlalu panjang
  • Hasil domain seperti “ditolak kembali karena tidak memiliki izin”
  • Pengujian transisi keadaan seperti ‘mengupdate sebagai menunggu setelah metadata diunduh diverifikasi’

Penggunaan kasus yang sering rusak:

  • Menginspeksi panggilan helper internal
  • Mengklaim urutan metode privat
  • menggantikan 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.

Pengujian untuk CI, Capacitor, dan Aplikasi Electron

Jika hanya satu mesin pengembang yang menjalankan tes, itu bukanlah jaring pengaman. Itu hanya 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 itu lebih penting lagi untuk Capacitor dan projek Electron, di mana pergeseran lingkungan menyebabkan gagal yang halus.

Jadikan CI sebagai jalur eksekusi default

At minimum, CI Anda harus menginstal dependensi dan menjalankan suite unit pada setiap perubahan. Pastikan perintahnya identik dengan pengembangan lokal saat mungkin.

Sebuah aliran kerja 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

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 mengkoppel suite uji Anda dengan 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. Pastikan panggilan plugin tetap di adapter. Uji logika aplikasi terhadap interface yang Anda kendalikan.

Menguji Electron main renderer dan IPC code

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

A reliable setup usually separates:

  • Uji unit renderer untuk model tampilan, keadaan, 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' });
});

Jika Anda kemudian mengubah implementasi internal dari satu bantuan ke bantuan lain, tes ini masih berlaku karena memverifikasi perilaku yang berlaku. Itu standar yang Anda inginkan di desktop dan mobile code.

Pertanyaan yang Sering Diajukan tentang Pengujian Unit JavaScript

Apa perbedaan antara unit integration dan E2E tests

A Unit Test Menguji satu bagian logika kecil secara terisolasi. pengujian integrasi menguji apakah beberapa komponen atau layanan bekerja sama dengan benar. pengujian akhir ke akhir Apakah kita harus mencapai coverages yang penuh?

Use unit tests for fast confidence in business rules. Use integration tests for seams such as storage, plugin wrappers, and IPC. Use E2E tests sparingly for the workflows that would seriously hurt if they broke.

Apakah kita harus mencapai penutupan penuh

Tidak. Pemeliharaan yang lengkap dapat mendorong tim menuju tes yang tidak berharga.

Coverage berguna ketika menunjukkan risiko code yang belum pernah diuji. Tidak berguna ketika insinyur menambahkan asertasi dangkal hanya untuk memuaskan dashboard. Jika suite Anda rapuh, lebih banyak coverage tidak akan menyelamatkannya.

Bagaimana cara 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 praktis seperti ini:

  • Pelindungi code aktif terlebih dahulu 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 sekitar plugin native, klien jaringan, panggilan filesystem, dan IPC Electron
  • Menghindari pola yang rapuh ketika memperkenalkan mock. Panduan dari Praktik-praktik pengujian JavaScript terbaik terutama sangat 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 memerlukan proses rilis yang lebih bersih seputar perubahan JavaScript, Capgo is one option to look at. It provides live updates for CapacitorJS and Electron apps, with rollout controls and observability, so teams can pair solid unit testing with a safer path to shipping web bundle changes without waiting on store review for every fix.

Update terus untuk Capacitor aplikasi

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

Terbaru dari Blog kami

Capgo memberikan Anda wawasan terbaik yang Anda butuhkan untuk membuat aplikasi mobile profesional yang sebenarnya.