NestJSでJestからVitestに移行してみた

はじめに

皆さんこんにちは!エンジニアの細川です。

今月はサイオステクノロジーのアドベントカレンダー、テーマは「サイオス社員が今年一年で新たに学んだ技術」です!

今月2回目の執筆ですが、今回はJavaScriptなどの開発に使える高速なテスト用パッケージVitestを紹介します!

Vitestとは

既にかなり話題になっているのでご存知の方も多いかもしれませんが、VitestはJavaScriptやTypeScriptの開発で利用可能なTest用のパッケージです。

もっとも有名なものはJestかと思いますが、VitestはJestとほとんど同じ機能を提供しており、移行もしやすいためVitestに移行している方も多いそうです。

Vitestのメリット

  1. 非常に高速
    1. VitestはJestに比べて非常に高速に動作します。依存関係を事前に解決しておくなどの処理で早くなるそうです。解決しなければならない依存関係によって変わると思いますが、NestJSのserviceの単体テストを回した場合、体感で3-5倍程度早くなったので初めて導入した時は驚きました。
  2. Jestからの移行が簡単
    1. describeit, expectなど、Jestで提供されている機能の多くが提供されており、移行がかなり簡単かと思います。
  3. BuildツールでViteを利用していなくても利用可能
    1. VitestはViteでbuildをすることで高速化しているようですが、プロジェクトのbuildツールでViteを採用していなくても利用することができます。buildツールを後から変更するのはいろいろ怖い部分もあるかと思うので、buildツールを変えなくてもいいというのもメリットかなと思います。
  4. ESMOnlyのパッケージを利用できる
    1. NestJSはcommonJSを前提としているので、あまり意識しないかもしれませんが、JestもNestJS同様commonJSを前提に動作しています。そのため、ESMOnlyのパッケージなどを利用する場合、別に設定をする必要がありました。しかしVitestではESMにも対応しているため、ESMOnlyのパッケージもそのまま利用できます。NestJSを使っていてもESMOnlyのパッケージを利用する場合もあるかと思うのでそのような場合はぜひVitestへの移行をお勧めします。(NestJSでESMOnlyパッケージを使う方法についてはこちらで解説しています。)

Vitestのデメリット

Vitestのデメリットとしては、既にJestで大量のテストを記述済みの場合などに完全に書き換えずに移行ができないという点です。

詳細はこちらのドキュメントを確認していただきたいのですが、mockの書き方や名前空間の有無など一部書き方が異なるため移行するにはそれらを書き換える必要があります。

思いつくデメリットとしてはこれくらいなので、許容できるプロジェクトではぜひ導入を検討してみてください。

前提の環境

今回のパッケージなどのバージョンは以下になります

パッケージ バージョン
Node.js 22.11.0
NestJS 10.0.0
Vitest 2.1.3

導入方法(NestJSの場合)

Vitestの導入方法を紹介します。今回はNestJSの場合ですが、他の場合でも手順はそんなに変わらないかなと思います。

Jestの削除

NestJSはデフォルトでJestがインストールされていると思いますので、Jestの削除をしておくことをお勧めします。

デフォルトの場合、testディレクトリにe2eテスト用のconfigファイルjest-e2e.jsonができていると思いますので、削除しておきます。

また、以下のコマンドでパッケージも削除しておきましょう

npm uninstall -D jest @types/jest ts-jest

Vitest導入

まずは以下のコマンドでパッケージのインストールを行います。

npm i --save-dev vitest unplugin-swc @swc/core @vitest/coverage-v8

その後vitest.config.mtsを作成します。

import { resolve } from "node:path";
import swc from 'unplugin-swc';
import { defineConfig } from 'vitest/config';

export default defineConfig({
  test: {
    globals: true,
    root: './',
    include: ["src/**/*.spec.ts"],
    exclude: ["node_modules", "dist"],
    coverage: {
      reporter: ["text", "json", "html"],
      reportsDirectory: resolve(dirname, "../coverage"),
      include: ["**/*.(t|j)s"],
    },
  },
  plugins: [
    // This is required to build the test files with SWC
    swc.vite(),
  ],
});

NestJSは基本的にcommonJSのはずですが、こちらのconfigファイルはESMの形式で書かれているので、拡張子を.tsではなく、.mtsにしている点に注意してください。

また、vitest.config.e2e.mtsも作成しておきます。

import swc from 'unplugin-swc';
import { defineConfig } from 'vitest/config';

export default defineConfig({
  test: {
    include: ['**/*.e2e-spec.ts'],
    globals: true,
    root: './',
  },
  plugins: [swc.vite()],
});

続いて、package.jsonにテスト用のスクリプトを設定します。

"vitest:common": "vitest --config ./vitest.config.mts",
"vitest:e2e": "vitest run --config ./vitest.config.e2e.mts",
"test": "npm run vitest:common run",
"test:watch": "npm run vitest:common",
"test:cov": "npm run vitest:common -- --coverage",
"test:e2e": "npm run vitest:e2e",

あとはnpm run testを叩くだけでテストを実行できます。

もちろん以下のようにファイル名を指定すれば一つだけ実行することなども可能です。

npm run test src/app.controller.spec.ts

configファイルなどの設定は皆さんのプロジェクトに合わせて読み変えてください。

まとめ

  1. Vitestは非常に高速!
  2. Jestから簡単に移行できる
    1. 一部書き方を変える必要あり
  3. Viteを使ってなくても利用可能
  4. ESMOnlyパッケージも利用できる

おわりに

今回はVitestの導入方法について紹介しました!

Vitestにはたくさんメリットがありますので、ぜひ皆さんのプロジェクトでも導入を検討してみてください!

今月はサイオステクノロジーのアドベントカレンダーで他にもたくさん記事が出ますのでぜひ読んでみてください!!(URLはこちら)

今回参考にさせていただいた記事

ご覧いただきありがとうございます! この投稿はお役に立ちましたか?

役に立った 役に立たなかった

0人がこの投稿は役に立ったと言っています。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です