vitest-v4 について
テストスイートの作成、設定、デバッグを行う開発者向けのVitest 4スキルです。Viteネイティブな手法に加え、実行、モック、カバレッジ、ブラウザテスト、複数プロジェクト設定を扱います。
主な機能
- 01Vitest 4の設定ガイダンス
- 02モックとクリーンアップのパターン
- 03カバレッジ設定
- 04Browser Modeでのテスト
- 05複数プロジェクト設定
活用シーン
- 01CIでウォッチなしのテストを実行
- 02テスト間に残るモックの修正
- 03未テストファイルのカバレッジ設定
- 04Browser Modeのスパイ問題の調査
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ nodnarbnitram/ claude-code-extensions --skill vitest-v4インストール後、Claude Code で/vitest-v4を入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
README.mdreferences/browser-mode-reference.mdcoverage-projects-reference.mdmocking-reference.mdpools-execution-reference.mdREADME.md詳細
Vitest 4 テストスキル
Vite ネイティブのパターンを使って、Vitest 4 のテストスイートを作成、設定、デバッグします。
開始する前に
このスキルを使うと、Vitest 4 でよくある 7 つ以上のミスを防ぎ、トークンを約 50%節約できます。
| 指標 | スキルなし | スキルあり |
|---|---|---|
| セットアップ時間 | 約 90 分 | 約 30 分 |
| よくあるエラー | 7 以上 | 0 |
| トークン使用量 | 多い(試行錯誤) | 少ない(既知のパターン) |
このスキルで防げる既知の問題
vitest runではなくウォッチモードを使うことによる、エージェントの実行停止- 削除された
coverage.allやcoverage.extensionsを使うことによる、カバレッジ設定の破損 - シールされた ESM 名前空間オブジェクトによる、Browser Mode のスパイ失敗
- restore/reset 設定の不足による、テスト間でのモックの漏洩
- 非推奨の
workspace用語を使うことによる、無効なマルチプロジェクト設定 - Jest のヘルパーを Vitest のテストに混在させることによる、誤った API の使用
vitest/browserではなく合成ヘルパーを使うことによる、不安定なブラウザー操作- 不適切な実行プールや分離モードの選択による、大規模なテストスイートの実行低速化や不安定化
クイックスタート
ステップ 1:エージェントに安全な実行のために Vitest 4 を設定する
// vitest.config.ts
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
environment: 'node',
restoreMocks: true,
clearMocks: true,
coverage: {
provider: 'v8',
include: ['src/**/*.{ts,tsx}'],
},
},
});
重要な理由: Vitest 4 では coverage.all と coverage.extensions が削除されました。また、エージェントや CI 環境では、1 回限りの実行とモックの自動クリーンアップが必要です。
ステップ 2:Jest API ではなく Vitest API でテストを書く
import { describe, expect, it, vi } from 'vitest';
import { addUser } from './add-user';
import * as api from './api';
describe('addUser', () => {
it('returns the created user', async () => {
vi.spyOn(api, 'createUser').mockResolvedValue({ id: '1', name: 'Ada' });
await expect(addUser('Ada')).resolves.toEqual({ id: '1', name: 'Ada' });
});
});
重要な理由: モック API としてサポートされているのは vi です。jest.fn() や Jest 専用のパターンを混在させると、分かりにくいエラーが発生し、オートコンプリートの質も低下します。
インポートのルール: プロジェクトで
globals: trueが明示的に有効になっている場合を除き、describe、it、expect、viはvitestからインポートしてください。
ステップ 3:正しいランタイムコマンドを使う
vitest run
vitest run --coverage
vitest run path/to/example.test.ts
重要な理由: 開発時に run を付けずに vitest を実行すると、デフォルトでウォッチモードが起動します。これはエージェント、CI、非対話型の検証には適していません。
重要なルール
必ず行うこと
- エージェントや CI のワークフローでは、
vitest runまたはvitest --no-watchを使します - 型安全なモジュールモックには、
vi.mock(import('./module'))を優先します restoreMocks、clearMocks、またはmockResetを意図的に設定します- マルチプロジェクト設定には
projectsを使います。この名称への変更は Vitest 3.2 で始まり、以前のワークスペースファイルの使用方法は Vitest 4 で削除されています - 複数の
projectsで共通設定が必要な場合は、共有のベース設定を使います。明示的にオプトインしない限り、プロジェクトはルート設定を継承しません - テストされていないソースファイルもレポートに含めるには、
coverage.includeを使います - Browser Mode では、
vitest/browserのpageとuserEventを使います - 生の速度よりもネイティブモジュールやランタイムとの互換性が重要な場合は、
forksを優先します - AI にテストを生成させるときは、
vitest.config.tsと実装ファイルを共有します
絶対にしてはいけないこと
- Vitest のコードで
jest.fn、jest.spyOn、または Jest 専用のグローバルを使わないでください - Vitest 4 で削除された
coverage.allやcoverage.extensionsに依存しないでください - エージェント主導の検証で、通常のウォッチモードを使わないでください
- Browser Mode でネイティブ ESM のエクスポートに
vi.spyOnを使わないでください vi.mock()はファイル内の残りのコードが実行される前に巻き上げられることを忘れないでください- テスト間で環境変数やグローバルのスタブを復元し忘れないでください
よくある間違い
誤り — 削除されたカバレッジオプション:
export default defineConfig({
test: {
coverage: {
all: true,
},
},
});
正しい方法 — include グロブを使う:
export default defineConfig({
test: {
coverage: {
provider: 'v8',
include: ['src/**/*.{ts,tsx}'],
},
},
});
理由: Vitest 4 では coverage.all と coverage.extensions が削除されています。未カバーのファイルを含めるには、サポートされている方法である coverage.include を使います。
誤り — Browser Mode でシールされたエクスポートをスパイする:
import * as math from './math';
import { vi } from 'vitest';
vi.spyOn(math, 'add').mockReturnValue(10);
正しい方法 — スパイを有効にしたモジュールモックを使う:
import { vi } from 'vitest';
vi.mock(import('./math'), { spy: true });
理由: ネイティブのブラウザー ESM 名前空間オブジェクトはシールされているため、Browser Mode ではエクスポートに直接スパイを設定できません。
既知の問題の予防
| 問題 | 根本原因 | 解決策 |
|---|---|---|
| テストが終了しない | 非対話型セッションでウォッチモードが開始された | vitest run を使用します |
| カバレッジレポートに未テストのファイルが表示されない | coverage.include が設定されていない | ソースを明示的に指定するグロブを追加します |
| Browser Mode のスパイが例外をスローする、または何もしない | シールされた ESM エクスポートに vi.spyOn を使用している | vi.mock(import('./mod'), { spy: true }) を使用します |
| モックがテスト間で漏れる | クリーンアップ用フラグがない | restoreMocks / clearMocks / unstubEnvs を有効にします |
| アップグレード後に複数プロジェクトの設定が壊れる | 非推奨の workspace 用語、または削除された workspace ファイルパターンを引き継いでいる | projects と defineProject に切り替えます |
| ワーカーまたはプールの設定が機能しなくなる | 古い maxThreads、maxForks、または poolOptions を引き継いでいる | maxWorkers などの Vitest 4 のワーカー設定に移行します |
| プロジェクト固有の設定が予期せず消える | ルート設定の前提が projects に継承されていない | extends: true、mergeConfig、または明示的に共有ベース設定を使用します |
| AI が生成したテストで誤ったヘルパーが使われる | Jest のパターンが Vitest にコピーされている | vi、Vitest のインポート、Vitest のマッチャーに置き換えます |
| ブラウザテストがハングする | ダイアログが処理をブロックしている、または誤った user-event ユーティリティを使っている | ダイアログをモックし、vitest/browser のヘルパーを使用します |
| 高速なプールでネイティブモジュールに奇妙な問題が発生する | プロセス分離が必要なテストスイートに threads を選択している | forks に切り替えるか、スレッドの使用範囲を絞ります |
バンドルされたリソース
リファレンス
- モックのルールと巻き上げ →
references/mocking-reference.md - Browser Mode のプロバイダーと注意点 →
references/browser-mode-reference.md - カバレッジと複数プロジェクトの設定 →
references/coverage-projects-reference.md - プール、分離、永続キャッシュ →
references/pools-execution-reference.md - リファレンス一覧 →
references/README.md
設定リファレンス
vitest.config.ts
import { defineConfig, defineProject } from 'vitest/config';
import { playwright } from '@vitest/browser-playwright';
export default defineConfig({
test: {
projects: [
defineProject({
test: {
name: 'unit',
include: ['src/**/*.test.ts'],
environment: 'node',
},
}),
defineProject({
test: {
name: 'browser',
include: ['src/**/*.browser.test.ts'],
browser: {
enabled: true,
provider: playwright(),
instances: [{ browser: 'chromium' }],
},
},
}),
],
coverage: {
provider: 'v8',
include: ['src/**/*.{ts,tsx}'],
},
restoreMocks: true,
unstubEnvs: true,
setupFiles: ['./test/setup.ts'],
},
});
主な設定:
test.projects:安定した複数プロジェクト向けの用語です。名称変更は Vitest 3.2 で始まり、プロジェクトはルート設定のすべての値を自動的に継承するわけではないため、必要に応じて共有設定を再利用するベースにまとめてくださいcoverage.include:カバレッジ対象外のソースファイルをレポートに表示する必要がある場合に必須ですbrowser.provider:Vitest 4 では、playwright()などのプロバイダーパッケージからプロバイダーファクトリーをインポートしますrestoreMocks/unstubEnvs:ファイル間でのテストの汚染を防ぎますsetupFiles:テストファイルの実行前に、MSW、グローバル変数、ポリフィルなどの共有テスト初期化を実行します
プロジェクト構成
my-app/
├── src/
│ ├── feature.ts
│ ├── feature.test.ts
│ └── feature.browser.test.ts
├── vitest.config.ts
├── vite.config.ts
└── package.json
重要な理由: Node と Browser Mode のテストを明確に分けることで、プロバイダーの設定、テストの選択、トラブルシューティングが大幅に簡単になります。
適切な環境を選択する: ほとんどのコンポーネントテストや軽量な DOM アサーションには jsdom を優先してください。ネイティブのブラウザー API、実際のレイアウトやイベントの動作、またはスクリーンショットのアサーションが重要な場合は、Browser Mode を使用してください。
適切な実行モデルを選択する: 安定性とネイティブモジュールとの互換性を重視し、特に複数の環境が混在するテストスイートやインフラストラクチャーに依存するテストスイートでは forks を優先してください。threads は、テスト環境がワーカースレッドでの実行に安全であり、追加の速度に価値があると分かっている場合にのみ使用してください。
よくあるパターン
型安全なモジュールモックのパターン
import { beforeEach, describe, expect, it, vi } from 'vitest';
import { getUserName } from './get-user-name';
import * as api from './api';
vi.mock(import('./api'), () => ({
fetchUser: vi.fn(),
}));
describe('getUserName', () => {
beforeEach(() => {
vi.mocked(api.fetchUser).mockReset();
});
it('returns the fetched user name', async () => {
vi.mocked(api.fetchUser).mockResolvedValue({ id: '1', name: 'Ada' });
await expect(getUserName('1')).resolves.toBe('Ada');
});
});
Browser Mode の操作パターン
import { expect, test } from 'vitest';
import { page, userEvent } from 'vitest/browser';
import { render } from 'vitest-browser-react';
import { Counter } from './counter';
test('increments after click', async () => {
render(<Counter />);
await userEvent.click(page.getByRole('button', { name: /increment/i }));
await expect.element(page.getByText('1')).toBeInTheDocument();
});
インソーステストのパターン
export function sum(a: number, b: number) {
return a + b;
}
if (import.meta.vitest) {
const { it, expect } = import.meta.vitest;
it('adds numbers', () => {
expect(sum(1, 2)).toBe(3);
});
}
依存関係
必須
| パッケージ | バージョン | 用途 |
|---|---|---|
vitest | ^4 | テストランナーとアサーション/モック API |
vite | ^6 | Vite を利用した共有モジュールパイプライン |
node | >=20 | Vitest 4 に必要なランタイム |
オプション
| パッケージ | バージョン | 用途 |
|---|---|---|
@vitest/coverage-v8 | ^4 | AST リマッピングによる高速かつ正確なカバレッジ |
@vitest/coverage-istanbul | ^4 | Istanbul カバレッジバックエンド |
@vitest/browser-playwright | ^4 | Browser Mode 用の Playwright プロバイダー |
@vitest/browser-webdriverio | ^4 | Browser Mode 用の WebdriverIO プロバイダー |
@vitest/browser-preview | ^4 | Browser Mode 用のプレビュープロバイダー |
公式ドキュメント
トラブルシューティング
エージェントの実行がいつまでも終了しない
症状: テストプロセスが終了しない、または Claude が追加のファイル変更を待ち続けます。
解決策:
vitest run
Browser Mode のテストでエクスポートをスパイできない
症状: vi.spyOn() が例外をスローする、何もしない、または Node モードでは動作するのにブラウザーでは失敗します。
解決策:
vi.mock(import('./module'), { spy: true });
カバレッジにテストのないソースファイルが含まれない
症状: レポートに、実行したテストで触れたファイルしか含まれません。
解決策:
coverage: {
provider: 'v8',
include: ['src/**/*.{ts,tsx}'],
}
アップグレード後に従来のワーカーまたはプールの設定が機能しない
症状: Vitest 4 への移行後、古い maxThreads、maxForks、singleThread、singleFork、または poolOptions の設定が機能しなくなります。
解決策:
test: {
maxWorkers: 4,
}
理由: Vitest 4 ではワーカー設定が簡素化され、プール固有の古いオプションがいくつか削除されました。
セットアップチェックリスト
このスキルを使用する前に、次の項目を確認してください。
- Node.js が
>=20である -
viteが>=6である -
vitest.config.tsまたはvite.config.tsにtestブロックが含まれている - エージェント/CI のコマンドで
vitest runを使用している - カバレッジが有効な場合、カバレッジプロバイダーのパッケージがインストールされている
- Browser Mode が有効な場合、ブラウザープロバイダーのパッケージがインストールされている