State of JSの結果で注目を集めているVitestをJestと比較
State of JSのアンケート結果を見て、テスティングライブラリの項目でVitestが注目されているのを知り、Jestとの違いを調べてみました。
Jest
JestはFacebookが開発したテスティングフレームワークで、Reactアプリケーションのテストのために設計されています。強力な機能と広範なコミュニティのサポートにより、JavaScriptエコシステムで広く使用されています。
// sum.js
export function sum(a, b) {
return a + b;
}
// sum.test.js (Jest)
import { sum } from './sum';
test('adds 1 + 2 to equal 3', () => {
expect(sum(1, 2)).toBe(3);
});
Jestはテストファイルを.test.jsまたは.spec.jsとして作成し、testまたはit関数を使ってテストケースを定義します。設定なしでそのまま実行できるのが大きな利点です。
npx jest
Vitest
VitestはViteエコシステムと密接に連携する最新のテストランナーです。高速な実行とシンプルな構成を提供し、特にViteベースのプロジェクトにおいて便利さが注目されています。
// sum.js
export function sum(a, b) {
return a + b;
}
// sum.test.js (Vitest)
import { describe, it, expect } from 'vitest';
import { sum } from './sum';
describe('sum', () => {
it('adds 1 + 2 to equal 3', () => {
expect(sum(1, 2)).toBe(3);
});
});
Vitestも似たような方法で動作しますが、describeやit関数はVitestからインポートします。Viteプロジェクトでは、高速かつ簡単に設定できる点が特徴です。
npx vitest
ライブラリの主な違い
速度
jest
初期実行速度が遅く、特に大規模プロジェクトではパフォーマンスのボトルネックが発生する可能性があります。
CommonJSモジュールシステムを基盤としているため、最新のバンドリング技術と比較すると速度が相対的に遅いです。
// processData.test.js
import { processData } from './processData';
import { fetchData } from './api';
jest.mock('./api'); // fetchDataをモック化
describe('processData', () => {
it('should return processed data', async () => {
// fetchDataのモック動作を定義
fetchData.mockResolvedValue({
title: 'sample title',
userId: 1,
});
const result = await processData();
expect(result).toEqual({
title: 'SAMPLE TITLE',
userId: 1,
});
expect(fetchData).toHaveBeenCalledTimes(1);
});
it('should throw an error if fetchData fails', async () => {
fetchData.mockRejectedValue(new Error('Network Error'));
await expect(processData()).rejects.toThrow('Network Error');
});
});
Vitest
Viteの高速なバンドリングとHMR(Hot Module Replacement)を活用することで、テストの速度が非常に速いです。
テスト環境が素早く起動し、コードを変更した後、即座に結果を確認することができます。
// processData.test.js
import { describe, it, expect, vi } from 'vitest';
import { processData } from './processData';
import { fetchData } from './api';
// fetchDataをモック化
vi.mock('./api', () => ({
fetchData: vi.fn(),
}));
describe('processData', () => {
it('should return processed data', async () => {
// fetchDataのモック動作を定義
fetchData.mockResolvedValue({
title: 'sample title',
userId: 1,
});
const result = await processData();
expect(result).toEqual({
title: 'SAMPLE TITLE',
userId: 1,
});
expect(fetchData).toHaveBeenCalledOnce();
});
it('should throw an error if fetchData fails', async () => {
fetchData.mockRejectedValue(new Error('Network Error'));
await expect(processData()).rejects.toThrow('Network Error');
});
});
設定と構成
Jest
Reactプロジェクトと一緒に使用する場合、初期設定が簡単で、多くの機能がデフォルトで提供されます。
しかし、React以外のプロジェクトや最新のツールチェーン(Vite、ES Modulesなど)との統合には追加の設定が必要です。
// jest.config.js
export default {
transform: {
'^.+\\.jsx?$': 'babel-jest',
},
testEnvironment: 'node',
};
Vitest
Viteベースのプロジェクトと自然に統合され、追加の設定なしで迅速に始められます。
Viteの設定ファイルをそのまま利用できるため、一貫した環境を維持することができます。
// vite.config.js
import { defineConfig } from 'vite';
import { configDefaults } from 'vitest/config';
export default defineConfig({
test: {
exclude: [...configDefaults.exclude, '**/node_modules/**'],
},
});
ES Module対応
Jest
CommonJSをデフォルトとしており、ES Modules(ESM)を使用する場合は追加の設定が必要です。
最新のJavaScript標準との互換性が完全ではない可能性があります。
// package.json
{
"type": "module",
"jest": {
"transform": {
"^.+\\.js$": "babel-jest"
}
}
}
Vitest
ES Moduleをデフォルトでサポートしており、最新のJavaScript標準を使用するプロジェクトに適しています。
ESMサポートが必要なViteベースのプロジェクトで強みを発揮します。
// sum.test.js
import { describe, it, expect } from 'vitest';
import { sum } from './sum';
describe('sum', () => {
it('works with ES Modules', () => {
expect(sum(1, 2)).toBe(3);
});
});
Jestが適している場合
React中心のレガシープロジェクトを扱う場合や、コミュニティのサポートが重要な場合
Vitestが適している場合
Viteベースの最新プロジェクトで、迅速なテスト環境を求める場合
結論
State of JSのアンケート結果からVitestの注目度が高まっていることを確認し、Jestと比較したところ、それぞれの長所と短所が明確に分かりました。
特に、迅速な開発サイクルが求められるプロジェクトでは、Vitestがより適していると感じました。
Discussion