Kalau kamu pernah ngulik project JavaScript atau TypeScript modern, kemungkinan besar kamu pernah berurusan sama yang namanya testing. Dan kalau udah ngomongin testing, dua nama yang paling sering muncul di percakapan developer akhir-akhir ini adalah Jest dan Vitest.

Dua-duanya test runner. Dua-duanya populer. Tapi punya filosofi dan pendekatan yang cukup beda di balik layar. Saya sendiri udah pakai Jest bertahun-tahun, dan mulai coba Vitest sejak tahun 2023. Jadi di artikel ini, saya mau cerita pengalaman pribadi, sekaligus ngasih perbandingan yang fair supaya kamu bisa menentukan mana yang cocok buat project kamu.

Enggak ada jawaban mutlak “A lebih baik dari B”. Tapi setelah baca ini, semoga kamu punya gambaran yang jelas.


Kenapa Testing Itu Penting, dan Kenapa Pilihan Tool-nya Juga Penting

Sebelum masuk ke perbandingan, saya mau sedikit ngomel dulu. Saya masih sering nemu project — bahkan di perusahaan yang lumayan besar — yang testing-nya minimalis banget. Alasannya macam-macam: “enggak ada waktu”, “nanti aja”, “fiturnya masih sering berubah”.

Padahal, tanpa testing, kamu tuh basically jalan di atas tali tanpa jaring pengaman. Satu refactor kecil bisa ngehancurin fitur yang udah jalan. Satu perubahan di satu file bisa nge-break logika di tempat yang bahkan kamu enggak sangka.

Nah, soal pilihan tool juga penting. Kenapa? Karena tool testing yang tepat bisa bikin proses nulis dan jalanin test jadi menyenangkan (atau setidaknya, enggak menyakitkan). Dan dua kandidat utama saat ini — Jest dan Vitest — punya vibes yang berbeda.

Jest itu veteran. Dibuat oleh Facebook (sekarang Meta), udah ada sejak 2014, dan jadi default test runner di banyak project JavaScript selama bertahun-tahun. Ekosistemnya matang, dokumentasinya lengkap, dan komunitasnya gede.

Vitest itu rising star. Muncul tahun 2022, dibangun oleh tim yang sama di balik Vite (Evan You dan kontributor lain). Vitest lahir karena ada kebutuhan yang belum terpenuhi oleh Jest, terutama soal integrasi dengan Vite dan kecepatan.

Jadi, pertarungan ini sebenernya bukan “lama vs baru” semata. Ini lebih ke soal filosofi, kebutuhan project, dan pengalaman developer.


Performa dan Kecepatan: Ini yang Paling Terasa

Kalau kamu cuma punya 20 test, beda waktu eksekusi mungkin enggak terlalu keliatan. Tapi coba kalau kamu punya ratusan bahkan ribuan test — di situlah perbedaan performa jadi sangat kentara.

Jest: Stabil, tapi Kadang Lambat di Project Besar

Jest menjalankan test di worker terpisah menggunakan worker_threads atau child_process. Ini artinya setiap file test punya isolasi yang bagus, tapi juga punya overhead yang enggak kecil.

Di project besar yang pernah saya tangani (sekitar 800+ test files), waktu eksekusi Jest bisa mencapai 2-3 menit. Itu belum termasuk waktu transformasi file — karena Jest pakai Babel atau ts-jest buat compile TypeScript, dan proses ini bisa makan waktu lumayan lama di awal.

// jest.config.js — contoh konfigurasi dasar
module.exports = {
  testEnvironment: 'jsdom',
  transform: {
    '^.+\\.tsx?$': 'ts-jest',
  },
  moduleNameMapper: {
    '^@/(.*)$': '<rootDir>/src/$1',
  },
  setupFilesAfterSetup: ['./jest.setup.js'],
};

Vitest: Gila Cepatnya

Vitest, di sisi lain, punya pendekatan yang berbeda. Dia memanfaatkan transformasi yang sudah dilakukan oleh Vite. Jadi kalau project kamu udah pakai Vite (atau framework yang berbasis Vite seperti Vue, Svelte, atau bahkan React via Vite), proses transformasi kode itu basically sudah dilakukan sekali — dan Vitest tinggal reuse hasilnya.

Hasilnya? Di project yang sama (800+ test files), waktu eksekusi Vitest bisa 3-5x lebih cepat. Bahkan di watch mode, perubahannya terasa instan.

// vitest.config.ts
import { defineConfig } from 'vitest/config';
import path from 'path';

export default defineConfig({
  resolve: {
    alias: {
      '@': path.resolve(__dirname, './src'),
    },
  },
  test: {
    environment: 'jsdom',
    globals: true,
    setupFiles: ['./vitest.setup.ts'],
  },
});

Perhatikan konfigurasinya? Mirip banget kan? Ini juga salah satu kelebihan Vitest — dia sengaja dibuat supaya compatible secara API dengan Jest. Jadi kalau kamu migrasi dari Jest ke Vitest, banyak test yang bisa jalan tanpa perubahan.

Benchmark Kasar di Project Saya

Saya sempat bikin perbandingan di salah satu project React + TypeScript (Vite-based):

MetrikJestVitest
Jalankan semua test (cold start)~45 detik~12 detik
Jalankan semua test (warm)~30 detik~8 detik
Watch mode — re-run 1 file~3 detik~0.3 detik
Memory usage~500MB~200MB

Angka-angka ini bisa beda tergantung project, tapi tren-nya konsisten: Vitest lebih cepat, terutama di project yang udah pakai Vite.


Fitur dan API: Mirip di Permukaan, Beda di Dalam

Jest dan Vitest punya API yang sangat mirip. Ini bukan kebetulan — Vitest memang sengaja didesain supaya compatible dengan Jest API. Jadi kalau kamu udah kenal describe, it, expect, mock, beforeEach di Jest, kamu enggak akan asing di Vitest.

Contoh Test di Jest:

// utils.test.ts (Jest)
import { sum, multiply } from './utils';

describe('Math utilities', () => {
  it('should sum two numbers correctly', () => {
    expect(sum(2, 3)).toBe(5);
  });

  it('should multiply two numbers correctly', () => {
    expect(multiply(4, 5)).toBe(20);
  });

  it('should handle zero correctly', () => {
    expect(sum(0, 0)).toBe(0);
  });
});

Contoh Test yang Sama di Vitest:

// utils.test.ts (Vitest)
import { describe, it, expect } from 'vitest';
import { sum, multiply } from './utils';

describe('Math utilities', () => {
  it('should sum two numbers correctly', () => {
    expect(sum(2, 3)).toBe(5);
  });

  it('should multiply two numbers correctly', () => {
    expect(multiply(4, 5)).toBe(20);
  });

  it('should handle zero correctly', () => {
    expect(sum(0, 0)).toBe(0);
  });
});

Bedanya cuma di import. Di Jest, describe, it, dan expect tersedia secara global (bisa dikonfigurasi). Di Vitest, kamu bisa import eksplisit dari 'vitest' atau set globals: true di config supaya mirip Jest.

Mocking

Mocking di kedua tool juga sangat mirip:

// Jest style
jest.mock('./api');
import { fetchData } from './api';

fetchData.mockResolvedValue({ data: 'test' });

// Vitest style
vi.mock('./api');
import { fetchData } from './api';

vi.mocked(fetchData).mockResolvedValue({ data: 'test' });

Di Vitest, jest.fn() diganti jadi vi.fn(), dan jest.mock() diganti jadi vi.mock(). Transisinya gampang.

Snapshot Testing

Dua-duanya support snapshot testing dengan cara yang mirip:

// Snapshot test — berlaku untuk Jest dan Vitest
it('should match the snapshot', () => {
  const user = createUser({ name: 'Budi', age: 25 });
  expect(user).toMatchSnapshot();
});

Native ESM Support

Nah ini salah satu perbedaan besar. Jest dari dulu punya masalah dengan ESM (ECMAScript Modules). Support ESM di Jest masih terasa hacky — butuh konfigurasi tambahan, kadang pakai flag --experimental-vm-modules, dan enggak jarang nemu bug aneh.

Vitest, karena dibangun di atas Vite yang memang mendesain ESM sebagai first-class citizen, punya support ESM yang jauh lebih baik. Kamu bisa pakai import/export tanpa masalah, dan enggak perlu khawatir soal CommonJS vs ESM compatibility.

Kalau project kamu udah full ESM (yang mana ini tren yang makin umum), Vitest jelas lebih mulus.

TypeScript Support

Jest butuh ts-jest atau Babel buat handle TypeScript. Ini work, tapi nambah layer konfigurasi.

Vitest? TypeScript support out of the box. Enggak perlu plugin tambahan. Tinggal tulis .ts, langsung jalan.

// Di Vitest, ini langsung work tanpa config tambahan
import { expect, it } from 'vitest';

interface User {
  name: string;
  age: number;
}

function createDefaultUser(): User {
  return { name: 'Anonymous', age: 0 };
}

it('should create default user', () => {
  const user = createDefaultUser();
  expect(user.name).toBe('Anonymous');
  expect(user.age).toBe(0);
});

Ekosistem dan Kompatibilitas: Di Mana Jest Masih Unggul

Jujur, meskipun Vitest banyak unggul di sisi performa dan fitur modern, ada area di mana Jest masih punya keunggulan.

Ekosistem Plugin yang Lebih Matang

Jest udah ada lebih dari 10 tahun. Artinya, plugin, preset, dan integrasi yang tersedia untuk Jest itu jauh lebih banyak. Kamu mau test React Native? Ada jest-react-native. Kamu mau test dengan custom transformer? Ada puluhan pilihan.

Vitest memang tumbuh cepat, tapi ekosistemnya belum sematang Jest. Kadang kamu harus bikin workaround sendiri untuk use case yang agak niche.

Integrasi dengan Framework Lama

Kalau project kamu pakai Create React App (CRA), misalnya, Jest udah jadi bawaan. Migrasi ke Vitest di project CRA itu bisa jadi project tersendiri. Tapi kalau project baru dengan Vite, ya Vitest jadi pilihan yang lebih natural.

Battle-Tested di Enterprise

Banyak perusahaan besar udah pakai Jest bertahun-tahun. CI/CD pipeline mereka udah di-tune untuk Jest. Tim mereka udah hafal Jest. Dalam konteks enterprise yang konservatif soal tooling, tetap pakai Jest kadang lebih masuk akal dari sisi risk management.

Tapi Vitest Mulai Mengejar

Perlu dicatat: Vitest sekarang udah dipakai di beberapa project besar. Nuxt, Vite, Astro, dan banyak library populer lainnya udah pakai Vitest. Jadi gap-nya makin kecil dari waktu ke waktu.


Migrasi dari Jest ke Vitest: Sesulit Apa?

Ini pertanyaan yang paling sering saya dapat. Jawaban singkatnya: enggak terlalu sulit, tapi bukan berarti enggak ada yang perlu diubah.

Langkah-langkah Umum

  1. Install Vitest dan (opsional) @vitest/ui buat visualisasi test.
npm install -D vitest @vitest/ui
  1. Buat vitest.config.ts (atau gabungin ke vite.config.ts).
// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

export default defineConfig({
  plugins: [react()],
  test: {
    globals: true,
    environment: 'jsdom',
    setupFiles: './src/setupTests.ts',
    include: ['src/**/*.{test,spec}.{js,ts,jsx,tsx}'],
  },
});
  1. Ganti global mocks — ubah jest.fn() jadi vi.fn(), jest.mock() jadi vi.mock(), dst.

  2. Update package.json scripts.

{
  "scripts": {
    "test": "vitest",
    "test:run": "vitest run",
    "test:coverage": "vitest run --coverage",
    "test:ui": "vitest --ui"
  }
}
  1. Jalankan test dan perbaiki error satu per satu.

Gotcha yang Sering Muncul

  • Module resolution: Jest dan Vitest kadang resolve module dengan cara beda, terutama untuk alias dan moduleDirectories.
  • Global vs explicit import: Kalau kamu set globals: true di Vitest, kamu enggak perlu import describe/it/expect. Tapi kalau kamu mau type safety yang lebih baik (terutama di TypeScript), import eksplisit lebih disarankan.
  • Timer mocks: jest.useFakeTimers() jadi vi.useFakeTimers(). Sintaksnya beda sedikit.

UI dan Developer Experience: Vitest Punya Kejutan

Salah satu fitur yang bikin saya jatuh cinta sama Vitest adalah Vitest UI. Kamu bisa buka browser dan lihat hasil test di interface visual yang interaktif. Ini terasa seperti upgrade besar dibanding cuma baca output di terminal.

npx vitest --ui

Selain itu, Vitest juga punya fitur in-source testing — kamu bisa nulis test di dalam file source code yang sama:

// src/utils.ts
export function sum(a: number, b: number): number {
  return a + b;
}

// Test di dalam file yang sama!
if (import.meta.vitest) {
  const { describe, it, expect } = import.meta.vitest;

  describe('sum', () => {
    it('should add two numbers', () => {
      expect(sum(1, 2)).toBe(3);
    });
  });
}

Ini konsep yang unik dan sangat cocok untuk unit test yang sederhana. Tentu saja, untuk test yang lebih kompleks, tetap disarankan pisah file.

Jest juga punya jest --watch yang bagus, dan ada tools pihak ketiga seperti jest-preview yang memberikan pengalaman visual. Tapi secara built-in, Vitest unggul di area ini.


Kapan Harus Pakai Jest, dan Kapan Harus Pakai Vitest?

Oke, ini bagian yang paling kamu tunggu-tunggu. Berdasarkan pengalaman saya, ini panduan sederhananya:

Pakai Jest Kalau…

  • Project kamu sudah pakai Jest dan berjalan baik. Jangan migrasi kalau enggak perlu.
  • Kamu pakai framework yang bawaannya Jest (misalnya Create React App).
  • Tim kamu sudah familiar banget sama Jest dan enggak mau belajar tool baru.
  • Kamu butuh ekosistem plugin yang sangat spesifik yang baru ada di Jest.
  • Project kamu pakai React Native (integrasi Jest + React Native sangat matang).

Pakai Vitest Kalau…

  • Project kamu pakai Vite (ini no-brainer).
  • Kamu pakai framework modern: Vue, Svelte, Solid, Astro, Nuxt, SvelteKit.
  • Performa adalah prioritas (project besar, CI/CD yang butuh cepat).
  • Kamu mau pakai ESM secara native tanpa pusing soal compatibility.
  • Kamu mau fitur modern seperti in-source testing dan built-in UI.
  • Kamu memulai project baru dan enggak ada constraint legacy.

Contoh Skenario Nyata

Bayangin kamu lagi bikin project React + TypeScript + Vite dari nol. Pilihan paling logis? Vitest. Konfigurasinya minimal, performanya cepat, dan ekosistem testing-nya (React Testing Library, jsdom, dll.) udah compatible.

Tapi kalau kamu di maintain project legacy yang udah 3 tahun pakai Jest dan punya 2000 test files? Jangan migrasi cuma karena “Vitest lebih cepat”. Cost migrasinya bisa enggak sebanding dengan benefitnya — kecuali kamu emang butuh fitur-fitur spesifik yang cuma ada di Vitest.


Tabel Perbandingan Lengkap

AspekJestVitest
Tahun rilis20142022
Dibuat olehMeta (Facebook)Evan You & komunitas Vite
PerformaBaik, tapi lambat di project besarSangat cepat, especially di project Vite
ESM supportParsial, butuh workaroundNative, first-class
TypeScript supportButuh ts-jest / BabelBuilt-in
APISendiri (sudah jadi standar)Compatible dengan Jest
Ekosistem pluginSangat matangBerkembang pesat
UIButuh tool pihak ketigaBuilt-in Vitest UI
In-source testingTidak supportSupport
Snapshot testingYaYa
Watch modeYaYa (lebih cepat)
Code coverageIstanbul (built-in)Istanbul / v8 (built-in)
Ideal untukProject existing, enterprise, React NativeProject Vite-based, modern frameworks

Kesimpulan

Kalau saya harus rangkum dalam satu kalimat: Vitest adalah masa depan testing di ekosistem Vite, sementara Jest tetap raja di ekosistem yang lebih luas dan legacy.

Dua-duanya tool yang solid. Dua-duanya bisa diandalkan buat nulis test yang berkualitas. Yang paling penting bukan tool-nya, tapi apakah kamu benar-benar nulis test. Tool yang paling canggih di dunia enggak ada gunanya kalau test coverage-nya 0%.

Kalau kamu lagi mulai project baru dengan Vite, saya highly recommend coba Vitest. Performanya bikin nagih, fiturnya modern, dan developer experience-nya top-notch. Tapi kalau project kamu udah jalan baik dengan Jest, enggak perlu FOMO. Jest tetap solid.

Testing itu soal disiplin, bukan soal tool. Tapi kalau tool-nya bikin proses testing jadi lebih menyenangkan? Why not, kan?


Ada Pertanyaan atau Mau Diskusi?

Kalau kamu punya pengalaman migrasi dari Jest ke Vitest, atau sebaliknya, atau punya pertanyaan spesifik soal testing di project kamu — jangan ragu buat hubungi saya di [email protected]. Saya senang bisa diskusi dan berbagi pengalaman seputar development. 🚀


FAQ

Apakah Vitest bisa drop-in replacement untuk Jest?

Secara API, ya — sangat mirip. Tapi bukan berarti 100% zero changes. Kamu tetap perlu update beberapa hal: ganti jest.fn() jadi vi.fn(), update config, dan sesekali adjust module resolution. Secara umum, effort migrasinya tergolong kecil — di project saya, butuh sekitar 1-2 hari untuk migrasi 500+ test files.

Apakah Vitest bisa dipakai di project yang bukan Vite-based?

Bisa, tapi enggak optimal. Vitest memang didesain untuk bekerja sama dengan Vite. Kalau project kamu pakai Webpack atau bundler lain, kamu bisa tetap pakai Vitest (dia punya standalone mode), tapi benefit performanya enggak akan semaksimal kalau kamu pakai Vite. Dalam kasus ini, Jest mungkin tetap lebih masuk akal.

Mana yang lebih bagus untuk testing React component?

Dua-duanya sama bagus. Untuk React component testing, yang lebih penting itu library yang kamu pakai — yaitu React Testing Library — bukan test runner-nya. React Testing Library works perfectly dengan Jest maupun Vitest. Jadi pilih test runner berdasarkan kebutuhan project secara keseluruhan, bukan cuma soal React testing.

Apakah Jest akan “mati” karena Vitest?

Enggak. Jest masih sangat aktif dikembangkan dan punya user base yang jauh lebih besar. Vitest memang tumbuh cepat, tapi Jest bukan “dinosaur” yang akan punah. Kemungkinan besar, kedua tool ini akan coexist untuk waktu yang lama. Pasar JavaScript cukup besar untuk dua test runner sekaligus.

Bagaimana dengan code coverage di Jest vs Vitest?

Dua-duanya support code coverage menggunakan Istanbul secara built-in. Di Vitest, kamu juga bisa pakai v8 coverage provider yang biasanya lebih cepat:

// vitest.config.ts
export default defineConfig({
  test: {
    coverage: {
      provider: 'v8', // atau 'istanbul'
      reporter: ['text', 'json', 'html'],
    },
  },
});

Kualitas coverage report-nya sebanding, jadi ini bukan faktor penentu yang besar.