VitestでJestからユニットテストを乗り換えたら、テスト実行がかなり速くなった話

Jestで動いていたユニットテストをVitestに移行したところ、設定が簡潔になりテスト実行速度がかなり上がりました。移行手順と感想をまとめます。

🙌 結論から

ViteプロジェクトのユニットテストをJestからVitestに移行したところ、テスト実行が体感で2〜3倍速くなり、設定ファイルもかなりシンプルになりました!

Jestはデフォルトでは ESModule の import がそのまま動かないため、Viteプロジェクトで使うには babel-jestts-jest の追加設定が必要でした。

VitestはViteの設定をそのまま共有できるので、パスエイリアスなどの設定を二重に書く必要がありません。

Jest互換のAPIで書かれているので、既存のテストコードはほぼそのまま使い回せました(^o^)/

💡 Jestを使っていたときの問題

MacBook Pro のキーボードと、ダークテーマのエディタに表示されたJavaScriptまたはTypeScriptのソースコードが写っている写真
普段コードを触っているデスクのイメージに近い一枚です📱 ユニットテストまわりの話も、この手元環境とも相性よさそうな感じ✨(雰囲気用の素材写真)

仕事で使っているViteプロジェクトで、ユニットテストにJestを使っていました。

JestはデフォルトではESModuleの import をそのまま扱えないため、ts-jest を導入して変換する設定が必要でした(´・ω・`)

// jest.config.ts(設定が複雑になりがちだった)
export default {
  preset: 'ts-jest',
  testEnvironment: 'node',
  transform: {
    '^.+\\.tsx?$': 'ts-jest',
  },
  moduleNameMapper: {
    '^@/(.*)$': '<rootDir>/src/$1',
  },
}

Viteでパスエイリアス(@/)を設定していたので、moduleNameMapper でその設定をJest側にも重複して書く必要がありました。

同じ設定を2箇所に書くのはメンテナンスコストが上がります。

実際に一度、パスエイリアスをVite側だけ変更してJest側の設定を更新し忘れてテストが全部落ちる、という事故が起きました(・_・;)

テストが増えてくると実行時間も3〜4分かかるようになってきて、CIの待ち時間がわりと長く感じでいました…

👀 Vitestへの移行手順

まずパッケージを追加します。

npm install --save-dev vitest

vite.config.tstest の設定を追加するだけで動き始めます!

// vite.config.ts
import { defineConfig } from 'vite'

export default defineConfig({
  test: {
    environment: 'node', // Reactコンポーネントのテストなら 'jsdom'
    globals: true,       // describe/it/expect をインポートなしで使いたいなら
  },
})

Viteの設定(パスエイリアスなど)が自動で引き継がれるので、Jestのような追加設定が不要です!

既存のテストファイルはほぼそのまま動きます。

jest.fn()jest.spyOn() など jest グローバルを直接参照している箇所は、vi.fn()vi.spyOn() に置き換える必要があります。

// Before (Jest)
const mockFn = jest.fn()
jest.spyOn(module, 'method')

// After (Vitest)
const mockFn = vi.fn()
vi.spyOn(module, 'method')

package.json のスクリプトを変更します。

{
  "scripts": {
    "test": "vitest run",
    "test:watch": "vitest"
  }
}

vitest run が一回だけ実行して終了するモード、vitest がウォッチモードです。

✨ 移行してみた感想

移行前後でテスト実行時間を比較してみました。

# Jest(移行前)
Tests: 82 passed
Time: 3m 12s

# Vitest(移行後)
Tests: 82 passed
Time: 1m 04s

3分超かかっていたテストが1分ちょっとまで短縮されました(^o^)/

設定ファイルが jest.config.ts を丸ごと削除して vite.config.ts の数行に集約されたのも、かなりすっきりしていい感じです。

ウォッチモード(vitest)もかなり快適で、ファイルを保存すると関連するテストだけを即座に再実行してくれます!

一点だけ気になったのは、一部のモジュールモッキングの挙動がJestと微妙に異なるケースがあったことです。

特に vi.mock がファイルの先頭に自動でホイスティングされる挙動は、知らないとはまりやすいかもしれません(^^;)

公式ドキュメントの Mocking セクションを一度読んでおくと安心です。

👍 まとめ

VitestはViteプロジェクトとの相性がとにかく良く、設定が楽なのにテスト実行速度は大幅に上がるという、費用対効果の高い移行でした。

Jest互換のAPIなので既存のテストをほぼ書き換えずに済み、移行コストは思ったより低かったです。

Viteを使っているプロジェクトでまだJestを使っているなら、ぜひ一度Vitestへの切り替えを検討してみてください。

テストを書く習慣が定着すると、コードへの自信がかなり変わりますね(^^)

テストはあまり書いてこなかったので、めっちゃいい経験になりました!