N-LAB

Nuxt 3 × Vitest × Vue Testing Libraryで単体テストの実行とカバレッジを取得する


目標


前提

※本手順書ではソースディレクトリを「src」に変更している想定としています。

・Nuxt 3.4.3
・Vitest 0.31.0
・Vue Testing Library 7.0.0
・happy-dom 9.10.9
・unplugin-auto-import 0.15.3
・vitest/coverage-c8 0.31.0

目次

  1. Vitestのインストールと初期設定
  2. 自動インポート設定
  3. カバレッジの取得


Vitestのインストールと初期設定

1. Vitestをインストールします。併せてVue Testing Library・happy-domもインストールします。

$ npm install --save-dev vitest @testing-library/vue happy-dom


2. プロジェクトのルート配下に「vitest.config.ts」を新規作成し、以下を記載して保存します。

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

export default defineConfig({
  plugins: [
    Vue(),
  ],
  resolve: {
    alias: {
      '~': path.resolve(__dirname, './src'),
      '@': path.resolve(__dirname, './src')
    }
  },
  test: {
    globals: true,
    environment: 'happy-dom'
  }
})

※本手順書ではソースディレクトリを「src」に変更している想定としています。

// nuxt.config.ts
export default defineNuxtConfig({
  srcDir: 'src/'
});


3. 「package.json」に以下を追加します。

{
  "config": {
    "path": "./src/unitTest/index.spec.ts"
  },
  "scripts": {
    "test:all": "vitest",
    "test:linux": "vitest $npm_package_config_path",
    "test:win": "vitest %npm_package_config_path%"
  },
}


4. テストを全件(全テストファイル)実施するには以下のコマンドを実行します。

$ npm run test:all


5. 任意のテストを実施するには以下のコマンドを実行します。予め「package.json」のconfigのpathに実行したい任意のテストファイルを指定しておきます。

Windowsの場合 $ npm run test:win
Linuxの場合   $ npm run test:linux


6. 「src」ディレクトリ内に「unitTest」ディレクトリを作成します。

$ cd src
$ mkdir unitTest


7. 「unitTest」ディレクトリ内に「index.spec.ts」を作成し、以下の内容を記載して保存します。

import { describe, expect, test } from 'vitest'
import { render } from '@testing-library/vue'
import Index from '~/pages/index.vue'

describe('Index', () => {
  test('Indexページにタイトルが表示されていること', () => {
    // Arrange
    const { container } = render(Index)

    // textContentは前後に空白を付与したテキストを返却するのでtrimで空白を除去する必要があります
    const title = container.querySelector('[data-testid="page-title"]')?.textContent?.trim()

    // Assert
    expect(title).toBe('Pages/index.vue')
  })
})


8. 「src」配下の「pages」ディレクトリ内に「index.vue」を作成し、以下の内容を記載して保存します。

<script lang="ts" setup>
</script>
<template>
  <h1 data-testid="page-title">
    Pages/index.vue
  </h1>
</template>


9. テストを実施します。テストが成功することを確認します。

$ npm run test:all
> test:all
> vitest
 DEV  v0.31.0 /xxxx/<project name>
 ✓ src/unitTest/index.spec.ts (1)
 Test Files  1 passed (1)
      Tests  1 passed (1)


自動インポート設定


1. 前項で作成した「src」配下の「pages」ディレクトリ内に存在する「index.vue」を以下の内容で修正して保存します。

<script lang="ts" setup>
// Nuxtが自動インポートするrefを使用する変数を新規追加
const testRef = ref(false)
</script>
<template>
  <h1 data-testid="page-title">
    Pages/index.vue
  </h1>
</template>


2. テストを実施します。テストが失敗することを確認します。

$ npm run test:all
> test:all
> vitest
 DEV  v0.31.0 /xxx/<project name>
 ❯ src/unitTest/index.spec.ts (1)
   ❯ Index (1)
     × Indexページにタイトルが表示されていること
⎯⎯⎯⎯⎯⎯⎯ Failed Tests 1 ⎯⎯⎯⎯⎯⎯⎯
 FAIL  src/unitTest/index.spec.ts > Index > Indexページにタイトルが表示されていること
ReferenceError: ref is not defined
 ❯ setup src/pages/index.vue:2:13
      1| <script lang="ts" setup>
      2| const tmp = ref(false)
       |             ^
      3| </script>


3. unplugin-auto-importをインストールします。

$ npm install --save-dev unplugin-auto-import


4. 「vitest.config.ts」のpluginsにAutoImportを新規追加します。AutoImportのimportsにはインポートしたいライブラリを記述します。プリセットが用意されているライブラリに関しては以下のように直接ライブラリ名を記載可能です。

// import文を追加
import AutoImport from 'unplugin-auto-import/vite'

export default defineConfig({
  plugins: [
    Vue(),
     // 以下を追加
    AutoImport({
      // インポートするライブラリにはプリセットが用意されています
      // https://github.com/antfu/unplugin-auto-import/tree/main/src/presets
      imports: ['vue', 'pinia', 'vue-router']
    })
  ],
})

※プリセットが用意されていないライブラリをインポートするには以下のように記載します。

export default defineConfig({
  plugins: [
    Vue(),
    AutoImport({
      imports: [
        {
          '@vueuse/core': [
            'useMouse', // = import { useMouse } from '@vueuse/core',
          ],
        }
      ]
    })
  ],
})


5. テストを実施します。テストが成功することを確認します。

$ npm run test:all
> test:all
> vitest
 DEV  v0.31.0 /xxxx/<project name>
 ✓ src/unitTest/index.spec.ts (1)
 Test Files  1 passed (1)
      Tests  1 passed (1)


カバレッジの取得

1. カバレッジの取得に必要なパッケージをインストールします。

$ npm install --save-dev @vitest/coverage-c8


2. 「vitest.config.ts」のtestに以下を追加して保存します。

export default defineConfig({
  test: {
    coverage: {
      provider: 'c8',
      include: ['src/**/*.{vue,js,ts}'],    // src配下の特定の拡張子のファイルのみをテスト対象に設定
      all: true,                            // 未テストのコードもカバレッジの対象にする
      reporter: ['html', 'clover', 'text']
    },
    root: '.',
    reporters: ['verbose'],
  }
});


3. 「package.json」のscriptsの「test:all/test:linux/test:win」を以下の内容で修正して保存します。

{
  "scripts": {
    "test:all": "vitest --coverage",
    "test:linux": "vitest --coverage $npm_package_config_path",
    "test:win": "vitest --coverage %npm_package_config_path%"
  },
}


4. テストを実施します。テストが成功し、カバレッジが表示されていることを確認します。

$ npm run test:all
> test:all
> vitest --coverage
 DEV  v0.31.0 /xxx/<project-name>
 ✓ src/unitTest/index.spec.ts (1)
   ✓ Index (1)
     ✓ Indexページにタイトルが表示されていること
 Test Files  1 passed (1)
      Tests  1 passed (1)
 % Coverage report from c8
-----------|---------|----------|---------|---------|-------------------
File       | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-----------|---------|----------|---------|---------|-------------------
All files  |     100 |      100 |     100 |     100 |                   
 index.vue |     100 |      100 |     100 |     100 |                   
-----------|---------|----------|---------|---------|-------------------



以上で全ての手順は完了になります