はじめに
皆さんこんにちは!エンジニアの細川です。
今月はサイオステクノロジーのアドベントカレンダー、テーマは「サイオス社員が今年一年で新たに学んだ技術」です!
今月2回目の執筆ですが、今回はJavaScriptなどの開発に使える高速なテスト用パッケージVitestを紹介します!
Vitestとは
既にかなり話題になっているのでご存知の方も多いかもしれませんが、VitestはJavaScriptやTypeScriptの開発で利用可能なTest用のパッケージです。
もっとも有名なものはJestかと思いますが、VitestはJestとほとんど同じ機能を提供しており、移行もしやすいためVitestに移行している方も多いそうです。
Vitestのメリット
- 非常に高速
- VitestはJestに比べて非常に高速に動作します。依存関係を事前に解決しておくなどの処理で早くなるそうです。解決しなければならない依存関係によって変わると思いますが、NestJSのserviceの単体テストを回した場合、体感で3-5倍程度早くなったので初めて導入した時は驚きました。
- Jestからの移行が簡単
describe
やit
,expect
など、Jestで提供されている機能の多くが提供されており、移行がかなり簡単かと思います。
- BuildツールでViteを利用していなくても利用可能
- VitestはViteでbuildをすることで高速化しているようですが、プロジェクトのbuildツールでViteを採用していなくても利用することができます。buildツールを後から変更するのはいろいろ怖い部分もあるかと思うので、buildツールを変えなくてもいいというのもメリットかなと思います。
- ESMOnlyのパッケージを利用できる
- 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ファイルなどの設定は皆さんのプロジェクトに合わせて読み変えてください。
まとめ
- Vitestは非常に高速!
- Jestから簡単に移行できる
- 一部書き方を変える必要あり
- Viteを使ってなくても利用可能
- ESMOnlyパッケージも利用できる
おわりに
今回はVitestの導入方法について紹介しました!
Vitestにはたくさんメリットがありますので、ぜひ皆さんのプロジェクトでも導入を検討してみてください!
今月はサイオステクノロジーのアドベントカレンダーで他にもたくさん記事が出ますのでぜひ読んでみてください!!(URLはこちら)