😸

簡単導入!Vitestで始める高速で快適なフロントエンドテスト

2024/12/27に公開

こんにちは、クラウドエースの赤嶺と賀です。

今回は単体テストに使用した「Vitest」というツールについて、
同僚の賀と一緒に調査し、思ったこと感じたことをご紹介します。

Vitest とは

Vitest は、JavaScript と TypeScript のテストフレームワークで、特に Vite プロジェクトと連携して高速なテストを実行できます。
軽量で設定が簡単なため、効率的にテストを行い、プログラムのバグを素早く検出・修正できます。

今回 Vitest を導入した理由

1.高速なパフォーマンス
   Jest と比較した際の実行時間が約 60%程度短縮されたという結果がある
   以下の記事で Jest と Vitest の実行時間を比較が紹介されていました
   https://zenn.dev/sa2knight/articles/migrating_vitest_from_jest

2.モダンな JavaScript/TypeScript プロジェクトとの親和性
   ネイティブ ES モジュールをサポートしており、
   トランスパイルを必要とせずにテストを実行する事ができる

3.設定の簡易さ
   Jest で必要だった Babel の設定が不要となり、
   最低限の機能はゼロコンフィグで使用開始可能で実装コストが軽い

4.Vite エコシステムとの統合
   Vite を使用したプロジェクト(Vue, React, Svelte など)でシームレスに導入可能。

公式にも記載があるように、パフォーマンスを非常に重視しているツールであり、高速な実行が売りです。
PJ の規模にもよるかもしれませんが、大きいプロジェクトほど恩恵がありそうですね!

下記にてよく使われているテストツール Jest と比較してみました。

Jest Vitest
機能 多様な機能を提供し、テスト機能を標準でサポート。
多数のプラグインや拡張機能が利用可能。
安定した信頼性と安定性を持つ。
高速なテストランナー、モジュールのホットリロードをサポート。
Vite プロジェクトでの直感的な使用が可能。
ECMAScript Modules(ESM)や TypeScript の強力なサポートを提供。
小さなバンドルサイズで、導入が容易。
パフォーマンス 比較的遅い場合がある、大規模プロジェクトでは特に速度に問題が生じることがある。
多機能がゆえ、依存関係が多くなりがちで、バンドルサイズが大きくなる場合がある。
テストの実行速度が非常に速く、開発者のフィードバックループが短縮できる。
軽量で依存関係が少ないため、パフォーマンスが良好。
使用シーン モックやスナップショットテストが必要な大規模なプロジェクトや、豊富な機能を最大限に活かしたい場合に最適。
企業や多くの大規模プロジェクトでの安定性が求められるシーンでの使用が推奨される。
Vite を使用しているプロジェクトや、モダンな JavaScript 開発を行っている場合に適している。
テスト速度が求められる開発サイクルの短いプロジェクトにおすすめ。

どちらにも良し悪しな点はありますが、
Jest だとプラグインが多いことや使用率の点から解決方法などが多い点が使いやすさに幅を感じます。
逆に Vitest は軽くて早い点が大きな利点になりそうです。

Nuxt3 で Vitest を利用する利点

Nuxt3 と Vitest を連携させることには多くの利点があります。
高速なビルドとリロード
Vite を基盤とすることで、ビルドとリロードの速度が非常に速く、開発体験が向上します。
これにより、開発者は即時のフィードバックを得られ、生産性が向上します。

一貫した開発環境
Nuxt3 と Vitest の両方が Vite を使用しているため、開発環境が統一され、設定やツールの互換性が確保されます。
これにより、開発者はツール間の摩擦を減らし、スムーズな開発プロセスを実現できます。

モダンな開発ツールの活用
Vite の最新技術を活用することで、開発プロセス全体がモダン化され、最新の開発ツールやプラクティスを取り入れることができます。

Vitest の導入

では、実際に Vitest を使うまでの準備について簡単に見ていきましょう。

  1. Vitest とテスト関連パッケージをインストールします(下記コマンドでできます)
    yarn add -D vitest @vitest/ui @vitejs/plugin-vue

  2. vitest.config.ts ファイルを作成します。下記の内容は参考例です。

import { defineConfig } from 'vitest/config';
import vue from '@vitejs/plugin-vue';

export default defineConfig({
  plugins: [vue()],
  test: {
    environment: 'jsdom',
  },
});
  1. package.json にテストスクリプトを追加します。同じく下記は参考例です。
{
  "scripts": {
    "test": "vitest"
  }
}
  1. 実際にテストファイルの作成を行います。
import { describe, it, expect } from 'vitest';

describe('example test', () => {
  it('should work', () => {
    expect(true).toBe(true);
  });
});
  1. テストの実行は下記コマンドで行えます。
    yarn test

Nuxt3 と Vitest の連携について

導入については様々な記事が出ているので割愛しますが、
実際の PJ で使う際にいくつかの追加の設定が必要だったのでご紹介します。

Nuxt3 の自動化機能について

Nuxt3 は効率的にアプリケーションを構築できるように、様々な自動化機能を提供しています。
これにより、手動での設定や冗長なコーディングを抑えられます。
しかし、Vitest でもこの機能を使うには設定を行う必要があるので注意が必要です。
私はこの設定がうまくできず、時間を取られた場所なので紹介したいと思います。

  • 自動インポート(Auto-imports 機能)
    • /components、/composable 直下のファイル、Vue3 API である ref、computed などを自動的にインポートする機能です
  • ルーティング
    • pages ディレクトリに Vue コンポーネントを配置するだけで、自動的にルーティングが設定されます。これにより、ルーティング設定の手間が大幅に軽減されます。
      • 例) pages/index.vue を作成すると、/ルートが自動的に生成され、特別な設定を行わずにページが表示されます。
  • レイアウトシステム
    • 共通のレイアウトを自動的に適用し、ページ間で一貫性を保ちます。

Vitest での自動 import 設定

Nuxt3 の自動インポートを機能を Vitest 上でも実現するために、unplugin-auto-importを利用します。
unplugin-auto-importは 自動インポート機能を提供する汎用プラグインで、上記 Nuxt3 のような自動インポート機能を実現できます。
こちらを導入することで、Vitest のテストファイル内でも自動インポートが可能になります。

インストール方法は下記コマンドを実行するだけです。

npm i -D unplugin-auto-import または yarn add -D unplugin-auto-import

設定例を下記に記載いたします。

import AutoImport from "unplugin-auto-import/vite";

export default defineConfig({
  plugins: [
    AutoImport({
      imports: [
        "vue", // Vueのコアライブラリからインポートしたい関数やコンポーネントを指定しています。
        "vue-router", //Vue Routerからインポートしたい関数やコンポーネントを指定しています。
        {
          vuetify: ["useTheme"], //VuetifyからuseTheme関数をインポートしたいことを示しています。
        },
        {
          //
          "#app": [
            "useAsyncData", //データをサーバーサイドで非同期に取得する際に使用する関数
            "useLazyAsyncData", //データを遅延読み込みする際に使用する関数関数
            "refreshNuxtData", //Nuxtのデータを更新する関数
            "clearNuxtData", //Nuxtのデータをクリアする関数
            "defineNuxtComponent", //Nuxtコンポーネントを定義する関数
            "useNuxtApp", //Nuxtアプリケーションにアクセスする関数
            "useRoute", //現在のルートにアクセスする関数
            "useRouter", //ルーターにアクセスする関数
            "useErrorHandler",
          ], //エラーハンドラにアクセスする関数
        },
        // ...他のライブラリやモジュール
      ],
      dirs: ["./utils"], //AutoImportがインポートを検索するディレクトリの指定
    }),
  ],
});

この設定を行うことで、vuevue-router、Nuxt3 の#appモジュール内の API がテストファイルに自動インポートされ、
コードの記述量が劇的に減るため見通しが良く、メンテンス性や可読性も高くなります。

知っていればなんてこと無い設定ですが、
実際にunplugin-auto-importが設定されていないとimport漏れによるエラーや冗長なコードになります。
実際に私は import 漏れによるReferenceErrorを何度見たかわかりません。

その他の設定

他にも知っていると便利な設定があるので紹介します。

エイリアスの設定

プロジェクト内で頻繁に使用されるパスを短縮するために、エイリアスが設定されています。
@~はプロジェクトのルートディレクトリを指し、#appは Nuxt3 の内部モジュールを指します。
このエイリアスによりインポートパスが短縮されより可読性が向上します。

resolve: {
  alias: {
    '@': path.resolve(__dirname, './'),
    '~': path.resolve(__dirname, './'),
    '#app': path.resolve(__dirname, 'node_modules/nuxt/dist/app'),
  },
},

test セクションの設定

vitest.config.js の設定
vitest.config.jsは、テスト環境としてjsdomが指定されています。
これにより、ブラウザ環境に近い形でテストを実行することができ、カバレッジや UI インターフェースを通じて、
テストの実行結果を視覚的に確認することができます。

test: {
  globals: true,
  environment: 'jsdom',
  reporters: ['json', 'default'],
  outputFile: './coverage/test-output.json',
},

globals: true は、Vitest がグローバル関数(例:describe、it、expect)を自動的に利用可能にすることを指定します。
environment: 'jsdom': ブラウザライクな環境でテストを実行します。
coverage: コードカバレッジレポートの設定を指定します。
includeexclude: テスト対象のファイルパターンと除外するディレクトリを指定します。

package.json の設定
package.json に実行スクリプトを定義すれば、簡単にテストやカバレッジの確認ができます。

"scripts": {
  "test": "vitest",
  "coverage": "vitest run --coverage",
  "test:ui": "vitest --ui",
}

まとめ

まだ知名度が低い Vitest ですが、使い勝手が良かったので紹介しました。
詰まってしまったとき、情報が少なく検索しても解決方法がわからないこともありますが、
できるだけナレッジを残していければと考えています。

参考程度に使ってみた際の実際の実行時間についても記載しておきます。
47 件のテストの実行に 3.02 秒という結果でした。

時間があるときに実際に同じテストで Vitest と Jest の実行時間について調べて見ようと思います!

参考資料

Nuxt 公式サイト
https://nuxt.com/docs/getting-started/installation

Vitest 公式サイト
https://cn.vitest.dev/guide/

Vite 公式サイト
https://ja.vitejs.dev/

github: unplugin-auto-import
https://github.com/unplugin/unplugin-auto-import

import の記述を不要にする unplugin-auto-import
https://zenn.dev/kazuwombat/articles/29c3252889f64c

Nuxt3 の Auto-imports 機能 (components/composables) を拡張する
https://zenn.dev/comm_vue_nuxt/articles/nuxt3-extend-auto-imports

Vite は使ってないけど Jest を Vitest に移行する
https://zenn.dev/sa2knight/articles/migrating_vitest_from_jest

Discussion