🧪

Next.jsにVitest導入したので備忘も兼ねて手順をまとめる

に公開

Next.jsプロジェクトでのVitest実装備忘録

はじめに

Next.jsプロジェクトにテスト環境を構築する際、従来はJestが主流でしたが、最近はVitestが注目を集めているようです。
VitestはViteベースの高速なテストランナーで、Next.jsとの相性も良く、設定も簡潔に済ませることができるとのことです。

参考:VitestとJestの比較サイト

今回はNext.jsプロジェクトにVitestを導入したのでその手順を備忘も兼ねてご紹介します。
良かったら参考にしてください。

Vitestを選ぶ理由

  • 高速な実行速度: Viteベースのため、テストの実行が非常に高速
  • ES Modulesネイティブサポート: モダンなJavaScript環境との相性が良い
  • シンプルな設定: 最小限の設定でテスト環境を構築可能
  • Hot Module Replacement: テストファイルの変更を即座に反映
  • Next.jsとの親和性: 最新のNext.jsバージョンで公式サポートが強化

1. パッケージのインストール

まず、必要なパッケージをインストールします。

npm install -D vitest @vitejs/plugin-react jsdom @testing-library/react @testing-library/dom vite-tsconfig-paths

各パッケージの役割

  • vitest: テストランナー本体
  • @vitejs/plugin-react: React コンポーネントのテストに必要
  • jsdom: ブラウザ環境をNode.js上で再現
  • @testing-library/react: React コンポーネントテスト用ライブラリ
  • @testing-library/dom: DOM操作用ライブラリ
  • vite-tsconfig-paths: TypeScriptのパスマッピングをViteで使用するため

2. vitest.config.tsの作成

プロジェクトルートにvitest.config.tsを作成します。

import { defineConfig } from 'vitest/config'
import react from '@vitejs/plugin-react'
import tsconfigPaths from 'vite-tsconfig-paths'
 
export default defineConfig({
  plugins: [tsconfigPaths(), react()],
  test: {
    environment: 'jsdom',
  },
})

設定の詳細

  • plugins:
    • tsconfigPaths(): @/componentsなどのパスエイリアスを解決
    • react(): JSX/TSXファイルの変換処理
  • test.environment:
    • 'jsdom': ブラウザ環境をシミュレート(React コンポーネントテストに必要)

3. package.jsonスクリプトの追加

package.jsonにテスト実行用のスクリプトを追加します。

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

スクリプトの説明

  • test: ウォッチモードでテストを実行(開発時)
  • test:run: 一度だけテストを実行(CI/CD用)
  • test:coverage: カバレッジレポート付きでテスト実行
  • test:ui: ブラウザでテスト結果を表示

4. テストファイルの作成例

実際のテストファイルの例を示します。

// src/__tests__/Button.test.tsx
import { describe, it, expect, vi } from 'vitest'
import { render, screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { Button } from '@/components/Button'

describe('Button', () => {
  it('正しくレンダリングされること', () => {
    render(<Button>テストボタン</Button>)
    expect(screen.getByRole('button')).toBeInTheDocument()
  })

  it('クリックイベントが発火すること', async () => {
    const handleClick = vi.fn()
    const user = userEvent.setup()
    
    render(<Button onClick={handleClick}>クリック</Button>)
    
    await user.click(screen.getByRole('button'))
    expect(handleClick).toHaveBeenCalledTimes(1)
  })
})

5. 追加設定(オプション)

Jest DOMの追加

より多くのマッチャーを使用したい場合は、@testing-library/jest-domを追加します。

npm install -D @testing-library/jest-dom

テストセットアップファイルを作成:

// src/test/setup.ts
import '@testing-library/jest-dom'

vitest.config.tsを更新:

export default defineConfig({
  plugins: [tsconfigPaths(), react()],
  test: {
    environment: 'jsdom',
    setupFiles: ['./src/test/setup.ts'],
    globals: true, // describe, it, expect をグローバルで使用可能に
  },
})

6. Vercelデプロイ時の注意点

問題の概要

Vercelにデプロイする際、Next.jsの本番ビルドプロセスでvitest.config.tsが型チェックの対象となり、開発依存関係のvitestパッケージが見つからずエラーが発生する場合があります。

Type error: Cannot find module 'vitest/config' or its corresponding type declarations.

解決方法:.vercelignoreの作成

プロジェクトルートに.vercelignoreファイルを作成し、テスト関連ファイルを除外します。

# .vercelignore
vitest.config.ts
src/__tests__/
**/*.test.ts
**/*.test.tsx
**/*.spec.ts
**/*.spec.tsx
src/test/

7. 実行方法

開発時のテスト実行

# ウォッチモードでテスト実行
npm run test

# 一度だけテスト実行
npm run test:run

# カバレッジレポート付きで実行
npm run test:coverage

まとめ

Vitestを今回導入してみました。
この記事がVitest導入の参考になれば幸いです。

  • 設定が簡潔: 最小限の設定でテスト環境が完成
  • 高速な実行: 開発効率が大幅に向上
  • モダンな機能: ES ModulesやTypeScriptとの親和性が高い

参考リンク

Discussion