Langkah ke Konten Utama

Panduan Komprehensif 2026 untuk Unit Tests JavaScript

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

Panduan Komprehensif 2026 untuk Unit Tests JavaScript

Anda mungkin berada di salah satu dua 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 akan semakin buruk di Capacitor dan Electron Aplikasi. Fitur sederhana dapat menyentuh logika bisnis bersama, 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 cerdas. Ini dimulai dengan batasan yang disiplin: uji logika murni secara langsung, isolasi efek sampingan, dan hindari menulis tes yang mengalami kegagalan ketika Anda mengubah nama fungsi internal.

Tabel Konten

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 Kode yang Sama. 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 pada Set Banyak Pilihan Utama. Jest, Mocha, dan Jasmine Selalu Dihadirkan Sebagai Framework Utama, dengan Jest seringkali diidentifikasi karena struktur tes bawaan, asertasi, pemalsuan, dan dukungan async dalam satu paket, seperti yang ditunjukkan di sini Lab Tes JavaScript Pluralsight.

Tabel Perbandingan Populer Framework Tes JavaScript Termasuk Jest, Mocha, Cypress, dan Playwright

Mengapa suatu framework tidak optional

Kesalahan pertama tim membuat 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 bersama:

  • Struktur Tes atau describe atau test atau it
  • atau atau
  • Hook untuk pengaturan dan penghapusan
  • Dukungan Asinkron untuk janji dan timer
  • Alat Palsu untuk ketergantungan luar

Jika tim Anda juga memerlukan pandangan yang lebih luas tentang otomatisasi tes di luar pekerjaan 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-in-one. Ia dilengkapi dengan sebagian besar yang dibutuhkan tim pada hari pertama.
Mocha lebih modular. Ini memberikan Anda runner dan mengharapkan Anda untuk menyusun sisa stack.

Fungsi Jest Mocha
Kompleksitas pengaturan Rendah untuk tim kebanyakan Tinggi karena Anda biasanya menambahkan library asertasi dan mocking
Asertasi Terintegrasi Sering digunakan bersama library lain
Pengembangan Mock Terintegrasi dalam Sering digunakan bersamaan dengan library lain
Pengujian asinkron Terintegrasi dalam dan sederhana Dukungan ada, tetapi tergantung lebih pada pengaturan sekitar
Alur kerja penutupan Sering diintegrasikan ke dalam alat rantai yang sama Banyak yang 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 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. Rekomendasi ini semakin kuat ketika aplikasi mencakup Capacitor Karena proyek-proyek tersebut sudah memiliki bagian yang cukup banyak. 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 stabil. Namun, untuk seorang insinyur menengah yang mengatur suite yang kuat dari awal, Jest biasanya mengurangi gesekan lebih banyak daripada yang dibuat.Catatan penting satu. 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 dalam yang cepat di mana pengujian unit JavaScript harus hidup.

Pengaturan Proyek dan Pengujian Pertama Anda

live update platform capacitor title

live_update_platform_capacitor_title

A setup uji coba yang bersih haruslah membosankan. Jika menambahkan tes pertama terasa rumit, kemungkinan suite tidak akan tetap sehat.

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

Konfigurasi Jest yang sederhana

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

Jika Anda sedang membangun aplikasi Capacitor secara lokal dan ingin lingkungan pengembangan Anda dalam kondisi sebelum menambahkan tes di sekitar logika bersama, panduan Capgo untuk membuat lingkungan lokal Capacitor Menulis tes sebelum __CAPGO_KEEP_0__

Write the test before the code

menulis tes terlebih dahulu __CAPGO_KEEP_0__organisasi tes dengan describe dan it, dan menentukan cek sekitar expect(...) klaim dalam panduan pengujian unit JavaScriptnya Yang penting karena perubahan test-first mengubah cara Anda merancang __CAPGO_KEEP_0__. Fungsi cenderung menjadi lebih kecil, dependensi menjadi lebih terlihat, dan efek sampingan berhenti mengalir ke logika yang seharusnya tetap murni..

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.

Pakai Arrange Act Assert setiap kali

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

Polanya

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

  1. dan masukan dan setiap pengaturan yang dibutuhkan.
  2. Melakukan dengan memanggil fungsi.
  3. Menyatakan pada hasilnya.

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

For Capacitor and Electron projects, that discipline matters more because your pure logic often sits next to native or desktop integration code. Keep the business rule testable without the platform runtime, and your first test won’t be your last useful one.

Menguasai Mocks dan Asinkron Code

Banyak bug di aplikasi code tidak berasal dari menambahkan 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 berdasarkan acara.

Batasi batasan, bukan semuanya

Panduan tes yang dapat dipertahankan menekankan Penggunaan coverage perilaku tunggal dan Satu aseransi 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 ini Artikel TestRail tentang tes unit yang dapat dipertahankan.

Peringatan itu sangat penting dalam JavaScript. Tim sering kali memulai dengan mengmock semua modul yang diimport dan akhirnya menguji apakah fungsi memanggil fungsi lain dalam urutan yang

Tujuan yang salah untuk tes yang berat mock:

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

Pilihan yang lebih baik:

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

Polanya yang lebih baik untuk Capacitor dan Electron code

Pada aplikasi mobile dan desktop, saya lebih suka memiliki layer penutup di atas API native atau platform. Kemudian, unit test menguji 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 menghantam layer layanan, bukan runtime secara langsung.

Untuk tim yang menguji logika rilis dan jalur pembaruan pada Capacitor aplikasi, Capgo memiliki panduan relevan tentang menguji pembaruan OTA Capacitor dengan skenario mock.

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

Tes aliran async tanpa fluktuasi

Menggunakan 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 pengguna.

Strategi Lanjutan untuk Tes yang Kuat

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

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

Menggunakan 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 unit test yang memberikan feedback tercepat dan gagal yang paling stabil. Panduan yang sama mengatakan bahwa suite unit penuh harus selesai dalam kurang dari 10 detik, dan cek pre-commit harus tetap kurang dari 5 detik, menurut panduan tes OpenReplay ini Saya menganggap itu sebagai alat anggaran, bukan agama. Jika sebagian besar upaya Anda berada di tes akhir-ke-akhir, tim Anda akan menunggu terlalu lama untuk mendapatkan feedback. Jika semuanya hanya unit-only, Anda akan melewatkan 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, serialisasi, kelayakan pembaruan, flag fitur, dan transformasi keadaan Tes integrasi
  • untuk adapter penyimpanan, pembungkus plugin, dan kontrak IPC tes unit
  • E2E tests untuk beberapa perjalanan kritikal seperti login, alur pembelian, sinkronisasi, atau prompt pembaruan

Pengukuran koverasi adalah sebuah lampu sorot, bukan target

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

Validator login yang memiliki uji kasus tepat memberikan nilai lebih dari sebuah 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 sedang memperketat kualitas sekitar validasi-heavy UI, panduan ini tentang menguasai validasi formulir frontend adalah sebuah komplement yang baik untuk strategi pengujian unit.

Pengujian perilaku bertahan dari refaktor

Suatu suite yang dapat diandalkan harus memungkinkan Anda merakit internal tanpa menulis ulang setengah dari pengujian. Cara termudah untuk mencapai hal itu adalah dengan mengklaim perilaku yang dapat dilihat bukal daripada detail implementasi.

Contoh penggunaan yang tahan lama:

  • Kondisi batas seperti input kosong, nilai-nilai mirip null, jenis data yang tidak valid, dan string yang terlalu besar
  • Hasil domain seperti “pengembalian ditolak karena izin yang hilang”
  • Transisi keadaan seperti “mengubah status update sebagai menunggu setelah metadata download diverifikasi”

Penggunaan kasus yang sering rusak:

  • menginspeksi panggilan bantuan internal
  • mengklaim metode privat yang berurutan
  • menggagalkan 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 ke jalur pipa rilis yang lebih luas.

Tes untuk CI, Capacitor, dan Aplikasi Electron

Tes yang hanya berjalan di satu mesin pengembang bukanlah jaring pengaman. Itu adalah kebiasaan lokal.

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

Jadikan CI sebagai jalur eksekusi default

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

Alur kerja GitHub dasar 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 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 untuk akses kamera, prompt biometrik, pendaftaran 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.

Pertanyaan yang Sering Diajukan 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 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 berusaha 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 memuaskan dashboard. Jika suite Anda sangat rapuh, coverase 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 disentuh selama pekerjaan fitur atau perbaikan bug
  • Ekstrak logika yang murni mengambil file yang sulit diuji sehingga aturan bisnis dapat diuji tanpa kebisingan framework atau runtime
  • Tambahkan pembungkus jahitan sekitar plugin native, klien jaringan, panggilan file sistem, dan IPC Electron
  • Tolak pola yang rapuh ketika memperkenalkan mock. Panduan dari praktik pengujian JavaScript terbaik terutama berguna di sini karena menyoroti masalah yang sering terlewatkan yaitu over-mocking dan tes yang rapuh yang mengikuti

Tujuan bukanlah keselesaan segera. Itu adalah perbaikan yang stabil di tempat-tempat di mana regresi menghabiskan tim paling banyak.


Jika tim Anda mengirimkan Capacitor atau Jika Anda ingin membandingkan alternatif kami dengan platform lain, Anda dapat mempertimbangkan beberapa pilihan berikut: kami memiliki integrasi yang lebih baik dengan Capacitor, kami memiliki kemampuan untuk memperbarui aplikasi secara langsung, dan kami memiliki dukungan yang lebih baik untuk plugin native. Namun, kami juga memiliki kelemahan kami sendiri, seperti biaya yang lebih tinggi dan kompleksitas yang lebih tinggi. Jadi, Anda harus mempertimbangkan kebutuhan Anda sendiri dan memilih platform yang paling sesuai dengan kebutuhan Anda. Kami juga memiliki integrasi yang lebih baik dengan Electron, kami memiliki kemampuan untuk memperbarui aplikasi secara langsung, dan kami memiliki dukungan yang lebih baik untuk plugin native. Namun, kami juga memiliki kelemahan kami sendiri, seperti biaya yang lebih tinggi dan kompleksitas yang lebih tinggi. Jadi, Anda harus mempertimbangkan kebutuhan Anda sendiri dan memilih platform yang paling sesuai dengan kebutuhan Anda. 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.

Update langsung untuk Capacitor apps

Ketika bug layer web masih aktif, 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.

Dukungan manusia dari Martin

Mulai Sekarang

Terbaru dari Blog Kami

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