テスト
Nuxtアプリケーションのテスト方法。
モジュールの作者であれば、モジュール作者向けガイドでより具体的な情報を見つけることができます。
Nuxtは、@nuxt/test-utils
を通じてNuxtアプリケーションのエンドツーエンドおよびユニットテストを一流のサポートで提供します。このライブラリは、現在Nuxt自体で使用しているテストやモジュールエコシステム全体のテストを支えています。
インストール
他のテスト依存関係を管理できるようにするために、@nuxt/test-utils
はさまざまなオプションのピア依存関係を提供します。例えば:
- 実行時のNuxt環境として
happy-dom
とjsdom
のどちらかを選択できます - エンドツーエンドテストランナーとして
vitest
、cucumber
、jest
、playwright
の中から選択できます - 組み込みのブラウザテストユーティリティを使用したい場合は
playwright-core
が必要です(テストランナーとして@playwright/test
を使用していない場合)
npm i --save-dev @nuxt/test-utils vitest @vue/test-utils happy-dom playwright-core
ユニットテスト
現在、Nuxt実行環境を必要とするコードのユニットテスト環境を提供しています。現在はvitest
のみをサポートしています(他のランタイムを追加するための貢献は歓迎します)。
セットアップ
-
@nuxt/test-utils/module
をnuxt.config
ファイルに追加します(オプション)。これにより、開発中にユニットテストを実行するためのVitest統合がNuxt DevToolsに追加されます。export default defineNuxtConfig({ modules: [ '@nuxt/test-utils/module' ] })
-
次の内容で
vitest.config.ts
を作成します:import { defineConfig } from 'vitest/config' import { defineVitestProject } from '@nuxt/test-utils/config' export default defineConfig({ test: { projects: [ { test: { name: 'unit', include: ['test/{e2e,unit}/*.{test,spec}.ts'], environment: 'node', }, }, await defineVitestProject({ test: { name: 'nuxt', include: ['test/nuxt/*.{test,spec}.ts'], environment: 'nuxt', }, }), ], }, })
@nuxt/test-utils
をvitestの設定でインポートする際には、package.json
に"type": "module"
を指定するか、vitestの設定ファイルを適切にリネームする必要があります。
例:
vitest.config.m{ts,js}
。
.env.test
ファイルを使用してテスト用の環境変数を設定することが可能です。
Nuxtランタイム環境の使用
Vitestプロジェクトを使用すると、どのテストがどの環境で実行されるかを細かく制御できます:
- ユニットテスト:通常のユニットテストは
test/unit/
に配置します - これらは速度のためにNode環境で実行されます - Nuxtテスト:Nuxtランタイム環境に依存するテストは
test/nuxt/
に配置します - これらはNuxtランタイム環境内で実行されます
代替案:シンプルなセットアップ
よりシンプルなセットアップを好み、すべてのテストをNuxt環境で実行したい場合は、基本的な設定を使用できます:
import { defineVitestConfig } from '@nuxt/test-utils/config'
export default defineVitestConfig({
test: {
environment: 'nuxt',
// Nuxt固有の環境オプションを設定することもできます
// environmentOptions: {
// nuxt: {
// rootDir: fileURLToPath(new URL('./playground', import.meta.url)),
// domEnvironment: 'happy-dom', // 'happy-dom'(デフォルト)または 'jsdom'
// overrides: {
// // 渡したい他のNuxt設定
// }
// }
// }
}
})
デフォルトでenvironment: 'nuxt'
を使用するシンプルなセットアップを使用している場合、必要に応じてテストファイルごとにNuxt環境からオプトアウトすることができます。
// @vitest-environment node
import { test } from 'vitest'
test('my test', () => {
// ... Nuxt環境なしでテスト!
})
このアプローチは推奨されません。Nuxt Viteプラグインが実行されますが、NuxtエントリとnuxtApp
が初期化されないハイブリッド環境を作成するためです。これにより、デバッグが難しいエラーが発生する可能性があります。
テストの整理
プロジェクトベースのセットアップでは、次のようにテストを整理することができます:
test/
├── e2e/
│ └── ssr.test.ts
├── nuxt/
│ ├── components.test.ts
│ └── composables.test.ts
├── unit/
│ └── utils.test.ts
もちろん、任意のテスト構造を選択できますが、Nuxtランタイム環境をNuxtエンドツーエンドテストから分離しておくことがテストの安定性にとって重要です。
テストの実行
プロジェクトセットアップを使用すると、異なるテストスイートを実行できます:
# すべてのテストを実行
npx vitest
# ユニットテストのみを実行
npx vitest --project unit
# Nuxtテストのみを実行
npx vitest --project nuxt
# ウォッチモードでテストを実行
npx vitest --watch
Nuxt環境内でテストを実行すると、happy-dom
またはjsdom
環境で実行されます。テストが実行される前に、グローバルなNuxtアプリが初期化されます(例えば、app.vue
で定義したプラグインやコードの実行を含む)。
これにより、テストでグローバル状態を変更しないように特に注意する必要があります(または、必要に応じて後でリセットする必要があります)。
🎭 組み込みモック
@nuxt/test-utils
はDOM環境のためのいくつかの組み込みモックを提供します。
intersectionObserver
デフォルトはtrue
で、IntersectionObserver APIの機能を持たないダミークラスを作成します。
indexedDB
デフォルトはfalse
で、fake-indexeddb
を使用してIndexedDB APIの機能的なモックを作成します。
これらはvitest.config.ts
ファイルのenvironmentOptions
セクションで設定できます:
import { defineVitestConfig } from '@nuxt/test-utils/config'
export default defineVitestConfig({
test: {
environmentOptions: {
nuxt: {
mock: {
intersectionObserver: true,
indexedDb: true,
}
}
}
}
})
🛠️ ヘルパー
@nuxt/test-utils
はNuxtアプリのテストを容易にするための多くのヘルパーを提供します。
mountSuspended
mountSuspended
を使用すると、Nuxt環境内で任意のVueコンポーネントをマウントでき、非同期セットアップやNuxtプラグインからのインジェクションにアクセスできます。
内部的には、mountSuspended
は@vue/test-utils
のmount
をラップしているため、渡せるオプションやこのユーティリティの使用方法についてはVue Test Utilsのドキュメントを参照してください。
例えば:
// @noErrors
import { it, expect } from 'vitest'
import type { Component } from 'vue'
declare module '#components' {
export const SomeComponent: Component
}
// ---cut---
// tests/components/SomeComponents.nuxt.spec.ts
import { mountSuspended } from '@nuxt/test-utils/runtime'
import { SomeComponent } from '#components'
it('can mount some component', async () => {
const component = await mountSuspended(SomeComponent)
expect(component.text()).toMatchInlineSnapshot(
'"This is an auto-imported component"'
)
})
// @noErrors
import { it, expect } from 'vitest'
// ---cut---
// tests/components/SomeComponents.nuxt.spec.ts
import { mountSuspended } from '@nuxt/test-utils/runtime'
import App from '~/app.vue'
// tests/App.nuxt.spec.ts
it('can also mount an app', async () => {
const component = await mountSuspended(App, { route: '/test' })
expect(component.html()).toMatchInlineSnapshot(`
"<div>This is an auto-imported component</div>
<div> I am a global component </div>
<div>/</div>
<a href="/test"> Test link </a>"
`)
})
renderSuspended
renderSuspended
を使用すると、@testing-library/vue
を使用してNuxt環境内で任意のVueコンポーネントをレンダリングでき、非同期セットアップやNuxtプラグインからのインジェクションにアクセスできます。
これは、Testing Libraryのユーティリティ(例:screen
やfireEvent
)と一緒に使用する必要があります。これらを使用するには、プロジェクトに@testing-library/vueをインストールしてください。
さらに、Testing Libraryはクリーンアップのためにテストグローバルに依存しています。これらをオンにするには、Vitestの設定で設定してください。
渡されたコンポーネントは<div id="test-wrapper"></div>
内にレンダリングされます。
例:
// @noErrors
import { it, expect } from 'vitest'
import type { Component } from 'vue'
declare module '#components' {
export const SomeComponent: Component
}
// ---cut---
// tests/components/SomeComponents.nuxt.spec.ts
import { renderSuspended } from '@nuxt/test-utils/runtime'
import { SomeComponent } from '#components'
import { screen } from '@testing-library/vue'
it('can render some component', async () => {
await renderSuspended(SomeComponent)
expect(screen.getByText('This is an auto-imported component')).toBeDefined()
})
// @noErrors
import { it, expect } from 'vitest'
// ---cut---
// tests/App.nuxt.spec.ts
import { renderSuspended } from '@nuxt/test-utils/runtime'
import App from '~/app.vue'
it('can also render an app', async () => {
const html = await renderSuspended(App, { route: '/test' })
expect(html).toMatchInlineSnapshot(`
"<div id="test-wrapper">
<div>This is an auto-imported component</div>
<div> I am a global component </div>
<div>Index page</div><a href="/test"> Test link </a>
</div>"
`)
})
mockNuxtImport
mockNuxtImport
を使用すると、Nuxtの自動インポート機能をモックできます。例えば、useStorage
をモックするには、次のようにします:
import { mockNuxtImport } from '@nuxt/test-utils/runtime'
mockNuxtImport('useStorage', () => {
return () => {
return { value: 'mocked storage' }
}
})
// your tests here
mockNuxtImport
は、テストファイルごとにモックされたインポートごとに一度だけ使用できます。実際にはvi.mock
に変換され、vi.mock
はVitestのドキュメントで説明されているようにホイストされます。
テスト間で異なる実装を提供するためにNuxtインポートをモックする必要がある場合は、vi.hoisted
を使用してモックを作成して公開し、それらのモックをmockNuxtImport
で使用することができます。その後、モックされたインポートにアクセスでき、テスト間で実装を変更できます。テスト間でモック状態の変更を元に戻すために、各テストの前または後にモックを復元することに注意してください。
import { vi } from 'vitest'
import { mockNuxtImport } from '@nuxt/test-utils/runtime'
const { useStorageMock } = vi.hoisted(() => {
return {
useStorageMock: vi.fn(() => {
return { value: 'mocked storage'}
})
}
})
mockNuxtImport('useStorage', () => {
return useStorageMock
})
// Then, inside a test
useStorageMock.mockImplementation(() => {
return { value: 'something else' }
})
mockComponent
mockComponent
を使用すると、Nuxtのコンポーネントをモックできます。
最初の引数はPascalCaseのコンポーネント名、またはコンポーネントの相対パスです。
2番目の引数はモックされたコンポーネントを返すファクトリ関数です。
例えば、MyComponent
をモックするには:
import { mockComponent } from '@nuxt/test-utils/runtime'
mockComponent('MyComponent', {
props: {
value: String
},
setup(props) {
// ...
}
})
// 相対パスやエイリアスも機能します
mockComponent('~/components/my-component.vue', async () => {
// またはファクトリ関数
return defineComponent({
setup(props) {
// ...
}
})
})
// または、モックコンポーネントへのリダイレクトにSFCを使用できます
mockComponent('MyComponent', () => import('./MockComponent.vue'))
// your tests here
Note: ファクトリ関数内でローカル変数を参照することはできません。Vue APIや他の変数にアクセスする必要がある場合は、ファクトリ関数内でそれらをインポートする必要があります。
import { mockComponent } from '@nuxt/test-utils/runtime'
mockComponent('MyComponent', async () => {
const { ref, h } = await import('vue')
return defineComponent({
setup(props) {
const counter = ref(0)
return () => h('div', null, counter.value)
}
})
})
registerEndpoint
registerEndpoint
を使用すると、モックデータを返すNitroエンドポイントを作成できます。APIにリクエストを送信してデータを表示するコンポーネントをテストしたい場合に便利です。
最初の引数はエンドポイント名(例:/test/
)です。
2番目の引数はモックデータを返すファクトリ関数です。
例えば、/test/
エンドポイントをモックするには:
import { registerEndpoint } from '@nuxt/test-utils/runtime'
registerEndpoint('/test/', () => ({
test: 'test-field'
}))
デフォルトでは、リクエストはGET
メソッドを使用して行われます。別のメソッドを使用するには、関数の代わりにオブジェクトを2番目の引数として設定します。
import { registerEndpoint } from '@nuxt/test-utils/runtime'
registerEndpoint('/test/', {
method: 'POST',
handler: () => ({ test: 'test-field' })
})
Note: コンポーネント内のリクエストが外部APIに向かう場合、
baseURL
を使用し、Nuxt環境オーバーライド設定($test
)を使用して空にすることで、すべてのリクエストをNitroサーバーに向けることができます。
エンドツーエンドテストとの競合
@nuxt/test-utils/runtime
と@nuxt/test-utils/e2e
は異なるテスト環境で実行する必要があるため、同じファイルで使用することはできません。
@nuxt/test-utils
のエンドツーエンドおよびユニットテスト機能の両方を使用したい場合は、テストを別々のファイルに分割できます。その後、特定のファイルごとに// @vitest-environment nuxt
コメントを使用してテスト環境を指定するか、ランタイムユニットテストファイルを.nuxt.spec.ts
拡張子で名前付けします。
app.nuxt.spec.ts
import { mockNuxtImport } from '@nuxt/test-utils/runtime'
mockNuxtImport('useStorage', () => {
return () => {
return { value: 'mocked storage' }
}
})
app.e2e.spec.ts
import { setup, $fetch } from '@nuxt/test-utils/e2e'
await setup({
setupTimeout: 10000,
})
// ...
@vue/test-utils
の使用
Nuxtでのユニットテストに@vue/test-utils
を単独で使用することを好み、Nuxtのコンポーザブル、自動インポート、コンテキストに依存しないコンポーネントのみをテストする場合は、次の手順に従ってセットアップできます。
-
必要な依存関係をインストールします
npm i --save-dev vitest @vue/test-utils happy-dom @vitejs/plugin-vue
-
次の内容で
vitest.config.ts
を作成します:import { defineConfig } from 'vitest/config' import vue from '@vitejs/plugin-vue' export default defineConfig({ plugins: [vue()], test: { environment: 'happy-dom', }, });
-
package.json
にテスト用の新しいコマンドを追加します"scripts": { "build": "nuxt build", "dev": "nuxt dev", ... "test": "vitest" },
-
次の内容でシンプルな
<HelloWorld>
コンポーネントapp/components/HelloWorld.vue
を作成します:<template> <p>Hello world</p> </template>
-
新しく作成したコンポーネントのシンプルなユニットテストを
~/components/HelloWorld.spec.ts
に作成しますimport { describe, it, expect } from 'vitest' import { mount } from '@vue/test-utils' import HelloWorld from './HelloWorld.vue' describe('HelloWorld', () => { it('component renders Hello world properly', () => { const wrapper = mount(HelloWorld) expect(wrapper.text()).toContain('Hello world') }) })
-
vitestコマンドを実行します
npm run test
おめでとうございます、Nuxtで@vue/test-utils
を使用したユニットテストを始める準備が整いました!テストを楽しんでください!
エンドツーエンドテスト
エンドツーエンドテストには、テストランナーとしてVitest、Jest、Cucumber、Playwrightをサポートしています。
セットアップ
@nuxt/test-utils/e2e
のヘルパーメソッドを利用する各describe
ブロック内で、開始前にテストコンテキストをセットアップする必要があります。
import { describe, test } from 'vitest'
import { setup, $fetch } from '@nuxt/test-utils/e2e'
describe('My test', async () => {
await setup({
// テストコンテキストオプション
})
test('my test', () => {
// ...
})
})
内部的には、setup
はbeforeAll
、beforeEach
、afterEach
、afterAll
で多くのタスクを実行し、Nuxtテスト環境を正しくセットアップします。
以下のオプションをsetup
メソッドに使用してください。
Nuxt設定
rootDir
: テスト対象のNuxtアプリを含むディレクトリへのパス。- タイプ:
string
- デフォルト:
'.'
- タイプ:
configFile
: 設定ファイルの名前。- タイプ:
string
- デフォルト:
'nuxt.config'
- タイプ:
タイミング
-
setupTimeout
:setupTest
が作業を完了するために許可される時間(ミリ秒単位)。これには、渡されたオプションに応じて、Nuxtアプリケーションのビルドやファイル生成が含まれる場合があります。- タイプ:
number
- デフォルト:
120000
または240000
(Windowsの場合)
- タイプ:
-
teardownTimeout
: テスト環境を解体するために許可される時間(ミリ秒単位)。例えば、ブラウザを閉じるなど。- タイプ:
number
- デフォルト:
30000
- タイプ:
機能
-
build
: 別のビルドステップを実行するかどうか。- タイプ:
boolean
- デフォルト:
true
(browser
またはserver
が無効、またはhost
が提供されている場合はfalse
)
- タイプ:
-
server
: テストスイート内でリクエストに応答するためのサーバーを起動するかどうか。- タイプ:
boolean
- デフォルト:
true
(host
が提供されている場合はfalse
)
- タイプ:
-
port
: 提供された場合、起動したテストサーバーのポートをこの値に設定します。- タイプ:
number | undefined
- デフォルト:
undefined
- タイプ:
-
host
: 提供された場合、新しいサーバーをビルドして実行する代わりにテストターゲットとして使用するURL。デプロイされたアプリケーションに対して「本物の」エンドツーエンドテストを実行する場合や、すでに実行中のローカルサーバーに対して実行する場合に便利です(これにより、テスト実行時間が大幅に短縮される可能性があります)。ターゲットホストエンドツーエンドの例を参照してください。- タイプ:
string
- デフォルト:
undefined
- タイプ:
-
browser
: 内部的には、Nuxtテストユーティリティはplaywright
を使用してブラウザテストを実行します。このオプションが設定されている場合、ブラウザが起動され、後続のテストスイートで制御できます。- タイプ:
boolean
- デフォルト:
false
- タイプ:
-
browserOptions
- タイプ:
object
で、以下のプロパティを持ちますtype
: 起動するブラウザのタイプ -chromium
、firefox
、webkit
のいずれかlaunch
: playwrightがブラウザを起動する際に渡されるオプションのobject
。完全なAPIリファレンスを参照してください。
- タイプ:
-
runner
: テストスイートのランナーを指定します。現在、Vitestが推奨されています。- タイプ:
'vitest' | 'jest' | 'cucumber'
- デフォルト:
'vitest'
- タイプ:
ターゲットhost
エンドツーエンドの例
エンドツーエンドテストの一般的なユースケースは、通常、プロダクションで使用される環境で実行されるデプロイされたアプリケーションに対してテストを実行することです。
ローカル開発や自動デプロイパイプラインでは、別のローカルサーバーに対してテストを実行する方が効率的であり、通常、テストフレームワークがテスト間で再ビルドするよりも高速です。
エンドツーエンドテストのために別のターゲットホストを利用するには、setup
関数のhost
プロパティに目的のURLを指定するだけです。
import { setup, createPage } from '@nuxt/test-utils/e2e'
import { describe, it, expect } from 'vitest'
describe('login page', async () => {
await setup({
host: 'http://localhost:8787',
})
it('displays the email and password fields', async () => {
const page = await createPage('/login')
expect(await page.getByTestId('email').isVisible()).toBe(true)
expect(await page.getByTestId('password').isVisible()).toBe(true)
})
})
API
$fetch(url)
サーバーレンダリングされたページのHTMLを取得します。
import { $fetch } from '@nuxt/test-utils/e2e'
const html = await $fetch('/')
fetch(url)
サーバーレンダリングされたページのレスポンスを取得します。
import { fetch } from '@nuxt/test-utils/e2e'
const res = await fetch('/')
const { body, headers } = res
url(path)
指定されたページの完全なURLを取得します(テストサーバーが実行されているポートを含む)。
import { url } from '@nuxt/test-utils/e2e'
const pageUrl = url('/page')
// 'http://localhost:6840/page'
ブラウザでのテスト
@nuxt/test-utils
内でPlaywrightを使用した組み込みサポートを提供しており、プログラム的にまたはPlaywrightテストランナーを介して使用できます。
createPage(url)
vitest
、jest
、cucumber
内で、createPage
を使用して設定済みのPlaywrightブラウザインスタンスを作成し、(オプションで)実行中のサーバーからのパスにポイントします。利用可能なAPIメソッドの詳細はPlaywrightのドキュメントで確認できます。
import { createPage } from '@nuxt/test-utils/e2e'
const page = await createPage('/page')
// `page`変数からすべてのPlaywright APIにアクセスできます
Playwrightテストランナーを使用したテスト
Playwrightテストランナー内でNuxtをテストするための一流のサポートも提供しています。
::code-group{sync="pm"}
npm i --save-dev @playwright/test @nuxt/test-utils
yarn add --dev @playwright/test @nuxt/test-utils
pnpm add -D @playwright/test @nuxt/test-utils
bun add --dev @playwright/test @nuxt/test-utils
::
前述のsetup()
関数と同じ設定詳細を使用して、グローバルなNuxt設定を提供できます。
import { fileURLToPath } from 'node:url'
import { defineConfig, devices } from '@playwright/test'
import type { ConfigOptions } from '@nuxt/test-utils/playwright'
export default defineConfig<ConfigOptions>({
use: {
nuxt: {
rootDir: fileURLToPath(new URL('.', import.meta.url))
}
},
// ...
})
テストファイルでは、@nuxt/test-utils/playwright
から直接expect
とtest
を使用する必要があります:
import { expect, test } from '@nuxt/test-utils/playwright'
test('test', async ({ page, goto }) => {
await goto('/', { waitUntil: 'hydration' })
await expect(page.getByRole('heading')).toHaveText('Welcome to Playwright!')
})
または、テストファイル内で直接Nuxtサーバーを設定することもできます:
import { expect, test } from '@nuxt/test-utils/playwright'
test.use({
nuxt: {
rootDir: fileURLToPath(new URL('..', import.meta.url))
}
})
test('test', async ({ page, goto }) => {
await goto('/', { waitUntil: 'hydration' })
await expect(page.getByRole('heading')).toHaveText('Welcome to Playwright!')
})
※このページは Nuxt.js 公式ドキュメントの翻訳ページ(非公式)です。
公式ドキュメントの該当ページはこちら:
https://nuxt.com/docs/4.x/getting-started/testing