Rilis Capacitor dapat melewati pengecekan akhir-ke-akhir dan masih mengirimkan invoice perhitungan yang rusak, flag fitur yang ketinggalan, atau cabang platform yang spesifik. Kegagalan sering kali dimulai lebih awal: tes unit masih menunjukkan perilaku lama, mock menyembunyikan ketergantungan yang berubah, atau CI menjalankan lingkungan yang berbeda dari mesin pengembang. Saat bug mencapai ponsel atau aplikasi desktop Electron, suite tes telah memberikan kepercayaan tanpa memberikan perlindungan.
Itulah mengapa Pemrograman Unit Jest sebaiknya dianggap sebagai keputusan alur kerja yang hidup, bukan hanya perintah komando. Pertanyaan yang berguna adalah praktis: berapa cepat seorang pengembang dapat percaya pada kegagalan, batasan-batasan apa yang harus tetap terisolasi, apa yang termasuk dalam coverage CI, dan apakah Jest masih sesuai dengan sistem modul proyek dan harapan feedback? Panduan ini berfokus pada keputusan-keputusan tersebut di atas layanan Node, aplikasi web, proyek Capacitor, dan aplikasi Electron. Untuk konteks yang lebih luas tentang di mana pengujian otomatis masuk dalam alur pengiriman, lihat pengujian otomatis dalam alur kerja perangkat lunak modern.

Isi Kandungan
- Mengapa Unit Testing Jest Masih Penting pada 2026
- Mengapa Pemrograman Unit Jest Masih Penting di 2026
- Membuat Unit Test yang Terpercaya Pertama Anda
- Strategi Mocking yang Benar-Benar Skala
- Mengintegrasikan Jest dengan CI dan Batasan Coverage
- Membuat Unit Test Jest yang Dapat Dipercaya pada Skala
- Rangkaian Keputusan dan Langkah-Langkah Berikutnya untuk Tim Anda
Mengapa Unit Testing Jest Masih Penting pada 2026
Jest tetap relevan karena menyelesaikan lebih dari sintaks asertasi. Ia memberikan tim tempat yang dapat diulang untuk memverifikasi logika bisnis, mengontrol batasan ketergantungan, menegakkan harapan coverage, dan menjalankan cek sebelum paket mobile atau desktop mencapai pengguna. Alur kerja ini penting ketika perilaku JavaScript yang sama dijalankan dalam shell browser, sebuah Capacitor WebView, renderer Electron, dan proses Node dengan API platform yang berbeda di sekitarnya.
Jest juga telah mendapatkan penggunaan yang luas. Facebook menciptakannya pada 2011 untuk sebuah ulasan JavaScript chat, kami mengunggahnya secara terbuka 2014dan Lembaga OpenJS melaporkan bahwa telah mencapai 38.000 GitHub bintang dan 17 juta unduhan mingguan oleh 2022 juta unduhan mingguan pada tahun 43.000 bintang dan 21 juta unduhan mingguan oleh 2024 (Sejarah Projek Jest dari OpenJS Foundation). Those figures don’t prove that Jest is right for every new repository, but they explain why teams often inherit a mature ecosystem, familiar conventions, and a large pool of existing examples.
Skipping unit tests in favor of end-to-end coverage looks cheaper until every small failure requires a full application launch, device setup, network path, and platform-specific diagnosis. E2E tests are valuable for release-critical journeys. They’re a poor substitute for fast, focused checks around tax calculations, update manifests, permission decisions, storage adapters, and error mapping.
Aturan yang Praktis: Keep Jest when its ecosystem reduces migration risk and your suite gives developers trustworthy feedback. Consider another runner when the runner itself has become the daily bottleneck.
Tetapkan Jest ketika ekosistemnya mengurangi risiko migrasi dan suite Anda memberikan feedback yang dapat dipercaya kepada pengembang. Pertimbangkan runner lain ketika runner itu sendiri telah menjadi bottleneck harian.
Memasang dan Mengonfigurasi Jest di Berbagai Lingkungan
Mulai dengan konfigurasi terkecil yang sesuai dengan runtime. Layanan Node biasanya memerlukan lingkungan default Jest dan skrip tes. Modul Capacitor yang menghadap browser atau Electron memerlukan global DOM, sedangkan TypeScript menambahkan keputusan transformasi yang dapat mempengaruhi debugging, kompatibilitas modul, dan perilaku startup.
Untuk proyek Node biasa, inisialisasi paket dan instal Jest sebagai dependensi pengembangan:
npm init -y
npm install --save-dev jest
npx jest --init
Konfigurasi yang dihasilkan adalah titik awal, bukan keputusan desain. Tinjau lingkungan tes, transformasi, alias modul, dan file pengaturan sebelum mengkomitinya.
Pilih transformasi TypeScript dengan sengaja
ts-jest adalah nyaman ketika repositori sudah bergantung pada perilaku kompiler TypeScript dan pengembang ingin diagnostik yang familiar. @swc/jest adalah menarik ketika kecepatan transpilasi sangat penting dan pengecekan tipe sudah berjalan sebagai perintah terpisah. Tidak ada opsi yang menggantikan pengecekan tipe, dan paket ESM berat mungkin memerlukan konfigurasi tambahan terlepas dari transformer yang digunakan.
| Pilihan | Node | TypeScript | Capacitor/Electron |
|---|---|---|---|
| Lingkungan | node |
node atau spesifik proyek |
jsdom untuk wajah DOM code |
| Mengubah | Biasanya tidak ada | ts-jest atau @swc/jest |
Pengubahan TypeScript plus Pengaturan DOM |
| Pengubahan TypeScript plus pengaturan DOM | Pengaturan ESM | Mengidentifikasi format paket | Memastikan dukungan transformer |
| Pengaturan Biasa | Minimal | jest.config.ts |
setupFilesAfterEnvmocks, API browser |
A Konfigurasi TypeScript menggunakan ts-jest Itu dapat terlihat seperti ini:
import type { Config } from 'jest'
const config: Config = {
preset: 'ts-jest',
testEnvironment: 'node',
setupFilesAfterEnv: ['<rootDir>/jest.setup.ts'],
clearMocks: true,
collectCoverageFrom: ['src/**/*.{ts,tsx}'],
}
export default config
Untuk repositori JavaScript atau campuran yang menggunakan Babel, pastikan file Babel eksplisit:
module.exports = {
presets: [
['@babel/preset-env', { targets: { node: 'current' } }],
'@babel/preset-typescript',
],
}
Tambahkan hanya shim browser yang dibutuhkan oleh code
Capacitor dan tes Electron seringkali mengimport code yang mengharapkan window.matchMedia atau IntersectionObserverSebuah file pengaturan dapat menyediakan shim yang dikendalikan tanpa mengaku bahwa Jest adalah perangkat nyata atau shell desktop:
Object.defineProperty(window, 'matchMedia', {
writable: true,
value: (query: string) => ({
matches: false,
media: query,
onchange: null,
addListener: () => {},
removeListener: () => {},
addEventListener: () => {},
removeEventListener: () => {},
dispatchEvent: () => false,
}),
})
class MockIntersectionObserver {
observe() {}
unobserve() {}
disconnect() {}
}
Object.defineProperty(window, 'IntersectionObserver', {
writable: true,
value: MockIntersectionObserver,
})
Jika sebuah dependensi ESM-only gagal selama pengumpulan, periksa transformIgnorePatterns and the package’s published format. Capacitor plugins can expose this problem when Jest ignores a dependency that still needs transformation. Jest’s newer releases have improved startup and memory behavior, but watch feedback can still trail ESM-focused alternatives in large projects (2026 Perbandingan Jest dan Vitest). Treat experimentalVMModules sebagai sebuah pengaturan kompatibilitas untuk menguji secara sengaja, bukan switch default.
For setup walkthrough yang fokus pada JavaScript, gunakan Capgo's guide pengujian unit untuk JavaScript. Selesaikan instalasi dengan perintah verifikasi nyata:
npx jest --runInBand
Uji coba asap yang berhasil mengkonfirmasi bahwa Jest dapat memuat proyek. Ini tidak mengkonfirmasi bahwa grafik modul produksi dan pengujian Anda berperilaku identik, jadi jaga tes impor ESM, DOM, dan plugin di mana jalur tersebut penting.
Membuat Tes Unit yang Terpercaya Pertama
Tes unit yang berguna menggambarkan perilaku yang dapat diamati dalam konteks yang dikendalikan. The Siapkan, Lakukan, Konfirmasi pola menjaga niat tersebut terlihat: siapkan input dan dependensi, panggil fungsi publik, kemudian verifikasi hasil atau efek yang dapat dilihat dari luar.
Anggap saja modul faktur mengexport fungsi ini:
export function calculateInvoiceTotal(
subtotal: number,
taxRate: number,
discountRate: number,
): number {
const discounted = subtotal * (1 - discountRate)
return Math.round(discounted * (1 + taxRate) * 100) / 100
}
Tes harus fokus pada perilaku keuangan, bukan variabel lokal bernama discounted:
import { calculateInvoiceTotal } from './calculateInvoiceTotal'
describe('calculateInvoiceTotal', () => {
it('applies percentage discount before tax', () => {
const subtotal = 100
const taxRate = 0.2
const discountRate = 0.1
const total = calculateInvoiceTotal(subtotal, taxRate, discountRate)
expect(total).toBe(108)
})
it('rounds the final amount to currency precision', () => {
const total = calculateInvoiceTotal(19.99, 0.2, 0)
expect(total).toBe(23.99)
})
})
Setiap it menentukan satu perilaku. Jika refaktor lebih lanjut mengubah perhitungan internal tetapi mempertahankan kontrak, tes-tes ini harus tetap berguna.

Tes asinkron memerlukan disiplin yang sama. Jest’s resolves dan rejects Membuat hasil yang diharapkan dari promise menjadi eksplisit:
it('returns an invoice from the API', async () => {
await expect(fetchInvoice('invoice-123')).resolves.toMatchObject({
id: 'invoice-123',
})
})
it('rejects when the invoice is missing', async () => {
await expect(fetchInvoice('missing')).rejects.toThrow('Invoice not found')
})
Kesalahan berbahaya adalah membuat harapan yang ditolak tanpa menunggu atau mengembalikannya. Panduan fokus Jest mengidentifikasi yang terlupakan await or return pernyataan sebagai penyebab positif palsu dan tes yang melewati tanpa peringatan yang jelas ("Pengujian Unit dengan JestSebuah tes yang tidak menunggu konfirmasi asertasi belum memverifikasi jalur gagal.
Hindari tiga kebiasaan yang menghasilkan kepercayaan rapuh:
- Menguji bantuan pribadi: Menguji perilaku yang diekspor kecuali bantuan itu mewakili batas publik yang bermakna.
- Mengaku keadaan internal: Nilai hasil, event yang diterbitkan, catatan yang disimpan, atau hasil output yang dapat dilihat.
- Menggunakan asertasi panggilan terlalu banyak:
toHaveBeenCalled()sendiri tidak mengatakan banyak. Periksa argumen yang relevan dan perilaku yang dihasilkan.
Daftar checklist PR dapat tetap singkat:
- Menguji perilaku mana yang ditangani?
- Mengikuti pola Arrange, Act, Assert?
- Mengharapkan ekspektasi async telah ditunggu?
- Menggunakan mock dependencies hanya di batas yang jelas?
- Menguji apakah test dapat bertahan jika ada refactor internal?
Menggunakan contoh spesifik komponen, Capgo’s Panduan Pengujian Unit React menerapkan prinsip-prinsip perilaku-terlebih dahulu pada hasil rendering dan interaksi yang dihadapi pengguna.
Strategi Penggantian yang Benar-Benar Mampu Skala
Mocking menjadi sulit ketika suatu suite berkembang karena setiap shortcut menciptakan kewajiban perawatan. Tangan-tangan yang ditulis jest.fn() Pertimbangkan validator pembayaran yang memanggil suatu SDK Stripe, merekam suatu event audit, dan mencapai suatu layanan risiko HTTP. Uji unit yang fokus mungkin menyadap logger, menggantikan pembayaran __CAPGO_KEEP_1__, dan mengintersepsi permintaan risiko. Teknik setiap kontrol batasan yang berbeda.
Consider a payment validator that calls a Stripe SDK, records an audit event, and reaches an HTTP risk service. A focused unit test might spy on the logger, replace the payment SDK, and intercept the risk request. Each technique controls a different boundary.
| Biaya pengaturan | Kemampuan | Beban perawatan | Pilihan terbaik | atau |
|---|---|---|---|---|
jest.fn() atau jest.spyOn() |
Rendah | Fokus | Rendah ketika lokal | Panggilan balik, logger, layanan yang diinjeksikan |
jest.mock() |
Menengah | Rendah hingga menengah | Dapat tumbuh dengan cepat | SDK, modul dengan efek sampingan yang mahal |
| MSW | Menengah | Lebih tinggi di perbatasan HTTP | Sentral | Memeriksa perilaku permintaan, kesalahan, dan kontrak respons |
Peniru manual untuk keputusan lokal
Gunakan spy ketika dependensi sudah diinjeksikan dan tes perlu mengamati atau mengontrol satu interaksi:
const audit = {
record: jest.fn(),
}
const result = await validatePayment(input, {
paymentClient,
audit,
})
expect(audit.record).toHaveBeenCalledWith(
expect.objectContaining({ event: 'payment.validated' }),
)
expect(result.status).toBe('approved')
Reset status antara kasus. Status bersama adalah sumber umum dari kegagalan Jest yang flaky, dan saran merekomendasikan menggabungkan beforeEach dengan membersihkan mock untuk mencegah hitungan panggilan dan kebocoran status (Penguasaan unit testing Jest).
Mock modul untuk SDK berat
Modul Stripe atau plugin asli sering melakukan setup segera setelah dimuat. Gantikan modul tersebut ketika memuat implementasi produksi akan memperkenalkan kunci, ikatan native, atau perilaku yang tidak relevan:
jest.mock('stripe', () => ({
payments: {
authorize: jest.fn(),
},
}))
Tes masih harus mengasumsikan nilai yang dikembalikan oleh aplikasi. Suatu panggilan SDK yang berhasil tanpa hasil yang bermakna hanya dapat membuktikan bahwa mock sudah dikonfigurasi.
MSW untuk celah HTTP
Untuk code yang mengelola konstruksi permintaan, analisis respons, ulang coba, atau penerjemahan kesalahan, MSW dapat menangkap layer HTTP sambil mempertahankan jalur permintaan:
server.use(
http.post('/risk/check', async () => {
return HttpResponse.json({ decision: 'review' })
}),
)
Biasanya ini memberikan kepercayaan yang lebih baik daripada menggantikan tingkat rendah fetch Memanggil dalam setiap tes. Ini juga membuat skenario respons lebih mudah dinamai dan digunakan kembali di lingkungan Node dan browser-like.
Mock di sambungan, bukan sambungan itu sendiri.
Over-mocking membuat tes yang melewati sementara integrasi pengkabelan rusak. Under-mocking membawa jaringan nyata, sistem file, jam, atau database ke dalam tes unit dan menghasilkan suite yang lambat dan tidak menentu. Biarkan logika murni bebas dari semua I/O, kemudian pindahkan verifikasi batas ke tes kontrak atau integrasi di mana interface yang relevan.
Mengintegrasikan Jest dengan CI dan Gates Coverage
CI harus menjawab dua pertanyaan yang berbeda. Pertama, apakah suite unit cepat menolak perubahan yang berbahaya? Kedua, apakah periksaan integrasi yang lebih lambat memastikan bahwa batasan penting masih berfungsi? Menempatkan setiap tes ke dalam satu perintah yang tidak berbeda membuat feedback lebih sulit untuk dipahami dan menggugah pengembang untuk mengabaikan suite.
Sebuah workflow Actions GitHub dapat menahan runtime Node, menggunakan file lock untuk caching dependensi, dan menjalankan periksa unit dengan mode CI Jest:
name: test
on:
pull_request:
push:
jobs:
unit:
runs-on: ubuntu-latest
strategy:
matrix:
node: [20, 22]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
cache: npm
cache-dependency-path: package-lock.json
- run: npm ci
- run: npm run test:unit, --ci --coverage
- uses: actions/upload-artifact@v4
with:
name: coverage-${{ matrix.node }}
path: coverage/
Skrip paket dapat memisahkan tes cepat dari pekerjaan integrasi:
{
"scripts": {
"test:unit": "jest --runInBand tests/unit",
"test:integration": "jest --runInBand tests/integration"
}
}
Pilih nilai ambang batas yang mencerminkan risiko daripada memilih angka universal dengan kebiasaan:
module.exports = {
collectCoverageFrom: ['src/**/*.{js,ts,tsx}'],
coverageThreshold: {
global: {
branches: 70,
functions: 80,
lines: 80,
statements: 80
}
}
}
Nilai-nilai tersebut adalah contoh konfigurasi, bukan standar industri yang diverifikasi. Tetapkan lantai sebenarnya dari basis lama repositori, kemudian tingkatkan ketika tim menambahkan penutupan yang bermakna. Pintu ketat dapat menghalangi perbaikan darurat jika mengukur yang dihasilkan atau berisiko rendah code. Pintu yang longgar dapat membiarkan jalur kritis memudar tidak terdeteksi.

Untuk repositori besar, gunakan sharding berbasis matrix hanya setelah isolasi tes suara. Setiap shard memerlukan kepemilikan jelas atas laporannya, dan status akhir harus membuat gagalnya terlihat dalam permintaan pull daripada menyembunyikannya dalam log. Tim juga dapat mengunggah coverase HTML sebagai artefak dan menerbitkan lcov data ke Codecov atau Coveralls, asalkan layanan tersebut telah dikonfigurasi untuk menggabungkan laporan dengan benar.
Baca Disciplin operasional CI bersamaan dengan desain alur kerja Anda, terutama jika beberapa aplikasi menggunakan satu repositori. Capgo’s guidance integrasi CI/CD bermanfaat ketika status tes harus terhubung dengan otomatisasi rilis dan pengembangan aplikasi mobile.
Mengembangkan Unit Test Jest yang Dapat Dipercaya pada Skala Besar
Suatu suite Jest besar dapat melewati secara konsisten sementara menguji hal yang salah. Kepercayaan menurun ketika tes bergantung pada detail implementasi, snapshot tumbuh melebihi tinjauan yang berguna, atau mock bersama mengubah perilaku jauh dari tes yang mengkonfigurasinya.
Snapshot memerlukan kepemilikan sadar. Mereka berfungsi baik ketika struktur yang dirender adalah kontrak nyata, seperti komponen stabil atau pesan yang diserialkan. Mereka menciptakan kebisingan ketika pengembang menyetujui perubahan luas tanpa memeriksa output. Regenerasi mereka secara sengaja, tinjau perbedaan, dan hapus file yang tidak lagi melindungi perilaku yang berarti.
Pakai lapisan daripada memaksa Jest untuk menguasai segalanya
Berikan setiap lapisan pengujian tugas yang sempit:
- Pengujian unit murni: Verifikasi perhitungan deterministik, parser, pengurang, keputusan kebijakan, dan pemetaan kesalahan tanpa akses ke jaringan atau sistem file.
- Pengujian kontrak: Periksa batasan modul, bentuk adapter, muatan permintaan, dan perilaku menghadap plugin.
- Pengujian E2E tipis: Uji jalur pengguna nyata yang kecil melalui web, Capacitor, atau shell Electron.
Penataan ini menjaga pengujian unit cepat sambil memeriksa batasan di mana mock dapat berhenti mewakili produksi. Ini juga menghindari mode gagal umum pada mobile: menguji pembaruan native atau alur izin seluruhnya melalui jalur UI yang mahal daripada mengisolasi logika keputusan JavaScript.
Jadikan satu perilaku per it() sehingga gagalnya tetap dapat diidentifikasi. Hanya klaim urutan ketika urutan itu milik kontrak. Fungsi palsu yang dapat ditanya, seperti repositori memori dengan metode yang mengekspos catatan yang disimpan, biasanya memberikan feedback yang lebih baik daripada nilai kembali yang ditetapkan secara keras yang hanya menyalin implementasi saat ini.
Suatu tes yang lulus harus menjelaskan apa yang pengguna atau modul tetangga dapat percayai, bukan bagaimana code hari ini teratur.
Jadwalkan ulasan kesehatan pengujian berulang. Ulas pengujian yang berubah-ubah, snapshot yang usang, setup yang tidak perlu, dan mock yang tidak lagi sesuai dengan perilaku produksi. Menghapus pengujian yang tidak berharga dapat lebih aman daripada menambahkan asseri ke pengujian yang sudah menutupi terlalu banyak.
Track flakiness in CI dashboards. If a test fails without a code change, preserve the failure evidence, isolate shared state, control time and randomness, and reduce worker pressure when the runner is overloaded. Set worker limits from measurements on your CI machines, because extra parallelism can increase contention and make the suite slower. Keep the worker setting documented with the runner configuration so future changes remain intentional.
Rangkuman Keputusan dan Langkah Selanjutnya untuk Tim Anda
Jest remains a sound default when a repository already has a stable suite, established transforms and mocks, and a team that values migration safety over runner experimentation. Compare alternatives when a new project is ESM-first, native feedback is a priority, or watch-mode reruns regularly interrupt development. Benchmark results can vary substantially by repository architecture and transformer work, so treat published comparisons as directional rather than promises.
Gunakan empat kriteria:
- Alat yang sudah ada: Tetapkan Jest ketika konfigurasi, utilitas tes, dan konvensi CI sudah berjalan.
- Alat yang sudah ada: Tetap gunakan Jest ketika konfigurasi, utilitas tes, dan konvensi CI sudah berjalan.
- Harapan umpan balik: Rekonsider runner ketika dependensi ESM hanya memerlukan pengecualian atau kerja sama khusus.
- Harapan feedback: Uji perubahan pengawasan yang representatif di repositori asli, bukan proyek demo kosong.
Vitest, pengujian Node bawaan, dan Playwright menangani kebutuhan yang berbeda. Playwright lebih cocok digunakan untuk pengujian E2E browser. Pengujung Node dapat digunakan untuk layanan Node yang fokus. Vitest seringkali cocok digunakan untuk proyek hijau ESM dan Vite. Jest masih cocok digunakan oleh tim yang bergantung pada mock yang matang, transformasi, dan konvensi CI yang ada. Pilih pengujung yang mempertahankan batasan yang dapat dipercaya sambil menjaga feedback yang dapat digunakan.
Reset 90 hari yang praktis
Bulan pertama, audit suite. Tugaskan pemilik untuk mengatalog tes yang flaks, snapshot mati, asseri yang terkait implementasi, dan tes yang melakukan I/O nyata. Hasilnya harus berupa daftar tertulis tentang penghapusan, perbaikan, dan batasan yang perlu coverage integrasi.
Bulan kedua, standarisasi desain. Tambahkan utilitas tes bersama, dokumentasikan konvensi mock, dan lakukan pelaporan coverage untuk paket penting. Rekam paket mana yang memiliki gate dan perilaku mana yang masih kurang tes fokus, sehingga baseline tetap dapat dinilai.
Bulan ketiga, stabilkan pengiriman. Kalibrasi pekerja CI, pisahkan pekerjaan unit dan integrasi, tetapkan lantai coverage berdasarkan risiko, dan dokumentasikan konvensi dalam sebuah dokumen hidup. TESTING.md. Pipa harus melaporkan gagal yang dapat diambil tindakan, sementara tes baru mengikuti batasan dan aturan mock yang sama.
Reviewlah suite pada jadwal yang berulang. Hapuslah snapshot yang usang, setup yang tidak perlu, dan mock yang tidak lagi sesuai dengan perilaku produksi. Test yang tidak berharga mungkin lebih baik dihapus daripada memperkuatnya dengan asertasi lain. Pantau kegagalan yang fluktuatif di CI, simpan bukti, isolasi kondisi yang dipartisipasikan, kendalikan waktu dan keacakan, dan kurangi tekanan pekerja ketika konten muncul. Tetapkan batasan pekerja dari pengukuran pada mesin CI dan simpannya dengan konfigurasi runner yang terdokumentasi.
Praktik-praktik ini termasuk dalam kategori yang lebih luas praktik terbaik pengembangan perangkat lunak. For a tested JavaScript fix targeting Capacitor or Electron users, Capgo can deliver signed JavaScript, CSS, configuration, and asset bundles through targeted channels, with rollback protection and release observability, without requiring a store review for every web-layer correction.
Jika tim Anda mengirimkan aplikasi Capacitor atau Electron, kunjungi Capgo to assess how live JavaScript updates fit controlled channels, staged rollouts, and rollback protection. Start by documenting Jest boundaries and CI gates, then define where Capgo belongs in the recovery path for fixes that need prompt delivery.