mcpField
V
vitest

vitest

github.com/jezwebテスト・品質1.1k1.7k 回インストール3 週間前に更新
リポジトリ

vitest について

プロジェクトに合わせて Vitest の設定、スクリプト、実行可能なサンプルテストを用意するスキルです。Jest からの移行にも対応します。

主な機能

  1. 01プロジェクト種別と既存設定の検出
  2. 02環境に合わせた Vitest 設定の生成
  3. 03セットアップファイルとテスト例の作成
  4. 04TypeScript 設定とスクリプトの追加
  5. 05Jest 移行のガイド

活用シーン

  1. 01React や Node プロジェクトへのテスト導入
  2. 02Cloudflare Workers のテスト設定
  3. 03monorepo の複数パッケージでの Vitest 設定

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/jezweb/claude-skills --skill vitest

インストール後、Claude Code で/vitestを入力して読み込まれたか確認します。

詳細

Vitest のセットアップ

プロジェクトの種類を検出し、適切な Vitest 設定を生成して、動作するテスト基盤を構築します。これはリファレンスカードではなく、ファイルを作成するスキルです。

ワークフロー

  1. 検出 — プロジェクトをスキャンして、種類と既存のセットアップを確認します
  2. 設定 — 環境に合わせて vitest.config.ts を生成します
  3. 足場の作成 — テストのセットアップ、ユーティリティ、サンプルテストを作成します
  4. 接続 — package.json のスクリプトと TypeScript 設定を追加します

Step 1: プロジェクトの種類を検出する

プロジェクトの種類を判定するため、次のファイルを読み取ります。

package.json          → dependencies, scripts, type field
tsconfig.json         → paths, compiler options
wrangler.toml         → Cloudflare Workers project
vite.config.ts        → existing Vite setup (extend, don't replace)
vitest.config.ts      → already configured? just fill gaps
jest.config.*         → migration candidate
src/                  → source structure

次のいずれかに分類します。

種類判定の手がかり環境
Cloudflare Workerswrangler.toml、@cloudflare/workers-types、cloudflare vite pluginWorkers 固有のセットアップを使用する node
React (Vite)@vitejs/plugin-react、react-domjsdom または happy-dom
React (SSR/TanStack Start)@tanstack/start、vinxi分割構成:サーバーには node、クライアントには jsdom
Node/Hono APIhono、express、react-dom なしnode
ライブラリexports フィールド、フレームワーク依存関係なしnode

既に vite.config.ts がある場合は、別の vitest.config.ts を作成せず、既存の設定を拡張します。Vitest は Vite 設定をネイティブに読み込みます。

Step 2: 依存関係をインストールする

検出した種類に基づいてインストールコマンドを生成します。

# Base (always)
pnpm add -D vitest

# React projects — add jsdom and Testing Library
pnpm add -D @vitest/coverage-v8 jsdom @testing-library/react @testing-library/jest-dom @testing-library/user-event

# Workers projects — add Cloudflare test utilities
pnpm add -D @vitest/coverage-v8 @cloudflare/vitest-pool-workers

# Node/Hono projects
pnpm add -D @vitest/coverage-v8

# If migrating from Jest, also remove:
pnpm remove jest ts-jest @types/jest jest-environment-jsdom babel-jest

プロジェクトのパッケージマネージャーを使用します(pnpm-lock.yaml、yarn.lock、bun.lockb、または package-lock.json を確認してください)。

Step 3: vitest.config.ts を生成する

Cloudflare Workers
import { defineWorkersConfig } from "@cloudflare/vitest-pool-workers/config";

export default defineWorkersConfig({
  test: {
    globals: true,
    poolOptions: {
      workers: {
        wrangler: { configPath: "./wrangler.toml" },
      },
    },
  },
});

プロジェクトが Cloudflare Vite プラグイン(@cloudflare/vite-plugin)を使用している場合は、代わりに既存の vite.config.ts に統合します。

/// <reference types="vitest/config" />
import { defineConfig } from "vite";
import { cloudflare } from "@cloudflare/vite-plugin";

export default defineConfig({
  plugins: [cloudflare()],
  test: {
    globals: true,
  },
});
React (Vite)
/// <reference types="vitest/config" />
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";

export default defineConfig({
  plugins: [react()],
  test: {
    globals: true,
    environment: "jsdom",
    setupFiles: ["./src/test/setup.ts"],
    css: true,
  },
});

既に vite.config.ts がある場合は、新しいファイルを作成せず、test ブロックを追加します。

Node / Hono API
import { defineConfig } from "vitest/config";

export default defineConfig({
  test: {
    globals: true,
    environment: "node",
  },
});
カバレッジを有効にする場合(任意の設定に追加)
  test: {
    // ... existing config
    coverage: {
      provider: "v8",
      reporter: ["text", "html", "lcov"],
      exclude: [
        "node_modules/",
        "**/*.config.*",
        "**/*.d.ts",
        "**/test/**",
      ],
    },
  },

Step 4: テストセットアップファイルを生成する

src/test/setup.ts を作成します(React プロジェクトのみ)。

import "@testing-library/jest-dom/vitest";

この単一のインポートで、すべてのカスタムマッチャー(toBeInTheDocument、toHaveTextContent など)が追加され、Vitest の expect.extend が自動的に登録されます。

Step 5: TypeScript 設定を追加する

tsconfig.json の compilerOptions に追加します。

{
  "compilerOptions": {
    "types": ["vitest/globals"]
  }
}

複数の tsconfig ファイルがあるプロジェクト(例:tsconfig.app.json + tsconfig.node.json)では、テストファイルを対象とする設定に追加します。通常はルートの tsconfig.json ですが、そこから拡張する tsconfig.test.json を作成してもかまいません。

Step 6: package.json のスクリプトを追加する

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

既存のスクリプトを上書きせず、既存の内容にマージします。

Step 7: サンプルテストを生成する

このプロジェクトに合ったパターンを示すテストファイルを1つ作成します。テストファイルは、独立した __tests__ ディレクトリではなく、実際のソースコードの隣に配置します。

Hono API ルートの場合(例:src/routes/health.ts):
import { describe, it, expect } from "vitest";
import { app } from "../index";

describe("GET /health", () => {
  it("returns 200 with status ok", async () => {
    const res = await app.request("/health");
    expect(res.status).toBe(200);

    const body = await res.json();
    expect(body).toEqual({ status: "ok" });
  });
});
React コンポーネントの場合(例:src/components/Button.tsx):
import { describe, it, expect } from "vitest";
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { Button } from "./Button";

describe("Button", () => {
  it("renders with label", () => {
    render(<Button>Click me</Button>);
    expect(screen.getByRole("button", { name: /click me/i })).toBeInTheDocument();
  });

  it("calls onClick when clicked", async () => {
    const user = userEvent.setup();
    const handleClick = vi.fn();
    render(<Button onClick={handleClick}>Click me</Button>);

    await user.click(screen.getByRole("button"));
    expect(handleClick).toHaveBeenCalledOnce();
  });
});
ユーティリティ関数の場合(例:src/utils/format.ts):
import { describe, it, expect } from "vitest";
import { formatCurrency } from "./format";

describe("formatCurrency", () => {
  it("formats whole numbers", () => {
    expect(formatCurrency(1000)).toBe("$1,000.00");
  });

  it("formats decimals", () => {
    expect(formatCurrency(49.9)).toBe("$49.90");
  });

  it("handles zero", () => {
    expect(formatCurrency(0)).toBe("$0.00");
  });
});

テストする実際のファイルをプロジェクトから選びます。架空のモジュールは作成しないでください。セットアップ後すぐに実行できるサンプルテストにします。

Step 8: 検証する

すべてが動作することを確認するため、テストを実行します。

pnpm test:run

失敗した場合は、原因を特定して修正します。よくある問題は次のとおりです。

エラー修正方法
Cannot find module 'vitest'インストールが完了していることと、node_modules/.vitest が存在することを確認します
ReferenceError: describe is not defined設定に globals: true を追加するか、tsconfig に types: ["vitest/globals"] を追加します
document is not defined環境が適切ではありません。React テストでは environment: "jsdom" を設定します
Cannot use import.metavitest.config の拡張子が .ts であること、プロジェクトに "type": "module" が設定されていること、または Vite が変換を処理していることを確認します
Workers のバインディングが未定義通常の vitest ではなく @cloudflare/vitest-pool-workers を使用し、wrangler.toml のパスを確認します

モックのリファレンス

以下のパターンは、セットアップ完了後にテストを書くためのものです。モックの例を求められた場合は、サンプルテストまたは src/test/examples.test.ts に含めます。

モジュールのモック(vi.mock)
import { vi, describe, it, expect } from "vitest";
import { getUser } from "./api";

vi.mock("./api", () => ({
  getUser: vi.fn(),
}));

it("mocks a module function", async () => {
  vi.mocked(getUser).mockResolvedValue({ id: 1, name: "Test" });
  const user = await getUser(1);
  expect(user.name).toBe("Test");
  expect(getUser).toHaveBeenCalledWith(1);
});
メソッドを監視する(vi.spyOn)
it("spies on console.warn", () => {
  const spy = vi.spyOn(console, "warn").mockImplementation(() => {});
  doSomethingThatWarns();
  expect(spy).toHaveBeenCalledOnce();
  spy.mockRestore();
});
フェイクタイマー
import { vi, beforeEach, afterEach, it, expect } from "vitest";

beforeEach(() => {
  vi.useFakeTimers();
  vi.setSystemTime(new Date("2026-01-15T10:00:00Z"));
});

afterEach(() => {
  vi.useRealTimers();
});

it("uses controlled time", () => {
  expect(new Date().toISOString()).toBe("2026-01-15T10:00:00.000Z");
});
グローバルスタブ
it("stubs fetch", async () => {
  const mockFetch = vi.fn().mockResolvedValue({
    ok: true,
    json: () => Promise.resolve({ data: "test" }),
  });
  vi.stubGlobal("fetch", mockFetch);

  const res = await fetch("/api/data");
  expect(mockFetch).toHaveBeenCalledWith("/api/data");

  vi.unstubAllGlobals();
});
スナップショットテスト
it("matches snapshot", () => {
  const result = generateConfig({ debug: true });
  expect(result).toMatchSnapshot();
});

it("matches inline snapshot", () => {
  expect({ status: "ok", count: 3 }).toMatchInlineSnapshot(`
    {
      "count": 3,
      "status": "ok",
    }
  `);
});
パラメーター化テスト
describe.each([
  { input: "hello", expected: "HELLO" },
  { input: "world", expected: "WORLD" },
  { input: "", expected: "" },
])("toUpperCase($input)", ({ input, expected }) => {
  it(`returns ${expected}`, () => {
    expect(input.toUpperCase()).toBe(expected);
  });
});

Jest からの移行

検出されたプロジェクトに Jest がある場合(依存関係に jest.config.*、@types/jest、ts-jest がある場合):

  1. 上記の手順に従って vitest.config.ts を生成する
  2. 既存のテストファイルのインポートを更新する:
// Before
import { jest } from "@jest/globals";
jest.mock("./api");
jest.fn();
jest.spyOn(obj, "method");

// After
import { vi } from "vitest";
vi.mock("./api");
vi.fn();
vi.spyOn(obj, "method");
  1. Jest パッケージを削除する:
pnpm remove jest ts-jest @types/jest jest-environment-jsdom babel-jest @jest/globals
  1. tsconfig を更新する — "types": ["jest"] を "types": ["vitest/globals"] に置き換えます

  2. テストを実行し、残っている問題を修正します

主な置き換え:

JestVitest
jest.fn()vi.fn()
jest.mock()vi.mock()
jest.spyOn()vi.spyOn()
jest.useFakeTimers()vi.useFakeTimers()
jest.clearAllMocks()vi.clearAllMocks()
jest.requireActual()vi.importActual()
@jest/globalsvitest
jest.config.jsvitest.config.ts

ワークスペースの設定(モノレポ)

複数のパッケージを含むモノレポプロジェクトの場合:

// vitest.workspace.ts
import { defineWorkspace } from "vitest/config";

export default defineWorkspace([
  "packages/*/vitest.config.ts",
]);

各パッケージにそれぞれの設定ファイルを用意します。ワークスペースファイルは、それらを参照するだけです。


このスキルで作成されるもの

実行後、プロジェクトには次のものが用意されます:

  • vitest.config.ts(または既存の vite.config.ts に追加された test ブロック)
  • src/test/setup.ts(React プロジェクトの場合)
  • vitest/globals 型を指定した更新済みの tsconfig.json
  • test スクリプトを含む更新済みの package.json
  • 実際のソースコードを対象とする、少なくとも 1 つの成功するサンプルテスト
  • インストール済みの依存関係

テストは最初の実行で成功するはずです。成功しない場合は、完了前に修正してください。

コメント