tech-vitest について
tech-vitest は、Vitest を使ったテストの作成と保守を支援するスキルです。モック、HTTP ハンドラー、タイマー、スナップショット、テスト設定を扱い、モックのホイスティングとテスト分離に重点を置きます。
主な機能
- 01モジュールと関数のモックガイド
- 02MSW v2 による HTTP モック
- 03フェイクタイマーと時間依存テスト
- 04スナップショットテストとレビュー
- 05フック、フィクスチャ、テスト設定
活用シーン
- 01テスト内でモジュールや API クライアントをモック
- 02MSW ハンドラーで HTTP リクエストを置き換え
- 03タイマーに依存するコードをテスト
- 04状態の漏れによる不安定なテストを調査
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ ravnhq/ ai-toolkit --skill tech-vitestインストール後、Claude Code で/tech-vitestを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
rules/_sections.mdassert-right-matcher.mdhooks-setup-teardown.mdmock-fake-timers.mdmock-msw-external-apis.mdmock-vi-fn.mdmock-vi-hoisted.mdmock-vi-mock.mdmock-vi-spyon.mdsnapshot-best-practices.md詳細
Vitest テストフレームワーク
高速で、Vite を活用したテストフレームワークです。Jest 互換 API とネイティブ ESM を備えています。Vitest の主な特長は次のとおりです。
- ウォッチモード — スマートなファイル監視により、開発中にすぐフィードバックを得られます
- ネイティブ TypeScript/JSX — Vite がコンパイルするため、追加の設定は不要です
- モックのエコシステム — モジュール用の
vi.mock()、HTTP リクエスト用の MSW v2、時間に依存するコード用のフェイクタイマー - スナップショットテスト — インラインスナップショットに対応し、スナップショットを自動管理します
- 並行テスト — 適切に分離した状態でテストを並列実行します
主な課題はテストの分離です。Vitest の vi.mock() に関する巻き上げルールでは、モック間で状態を共有するために vi.hoisted() が必要です。MSW v2 ではハンドラーの API が変更されています。スナップショットの更新は、意図的に行う必要があります。
ワークフロー
テストをセットアップしたり、テストケースを追加したりするときは、次の手順に従います。
- 範囲を特定する — どのような動作ですか?(ユニット/インテグレーション/E2E?)
- 依存関係を確認する — HTTP?タイマー?ほかのモジュール?
- 方針を選ぶ — モジュールには巻き上げを伴う
vi.mock()、HTTP には MSW、時間にはフェイクタイマーを使います - 共有状態を巻き上げる — モックでテストスコープの変数が必要な場合は、
vi.hoisted()を使います - ハンドラーをセットアップする —
beforeAll()で MSW サーバーを起動し、afterEach()でリセットします - アサーションとスナップショット — マッチャーを使い、安定した出力だけをスナップショットにします
- 検証する — カバレッジを確認しながら
vitest --watchを実行します
ルール
テストは関心事ごとに整理されています。
- モジュールのモック —
vi.mock()、vi.hoisted()、importOriginalを使った部分モック - 関数のモック — 戻り値、実装、呼び出し追跡を指定した
vi.fn() - メソッドのスパイ — オブジェクトのメソッドを置き換えずに監視する
vi.spyOn() - HTTP のモック — MSW v2 のハンドラー、
setupServer()、テストごとの上書き - フェイクタイマー —
vi.useFakeTimers()、vi.setSystemTime()、タイマーの進行 - スナップショット —
toMatchSnapshot()、インラインスナップショット、エッジケース - アサーション — テストのアサーションに使うマッチャーの選択
- フックとセットアップ —
beforeEach、afterEach、フィクスチャ、セットアップファイル
実装パターンと例については、rules/ を参照してください。
例
ポジティブトリガー
ユーザー:「この Vitest テストで API クライアントをモックし、偽のレスポンスを返すようにしてください。」
期待される動作:tech-vitest のガイダンスを使い、巻き上げルールと MSW のパターンに従って vi.mock() を適用します。
非トリガー
ユーザー:「ユーザーアカウント用の PostgreSQL データベーススキーマをセットアップしてください。」
期待される動作:tech-vitest を優先せず、より関連性の高いスキルを選ぶか、スキルを使わずに対応します。
-
エラー:条件式の中に
vi.mock()を置く -
原因:
vi.mock()は巻き上げられるため、条件式は無視され、予期しないモジュール状態につながります -
解決策:モックをファイルの先頭に移動し、条件付きのモック状態には
vi.hoisted()を使います -
エラー:変更内容を確認せずにスナップショットを更新する
-
原因:スナップショットはアサーションを介さないため、予期しない変更によってバグが見過ごされます
-
解決策:
-uで更新を受け入れる前に、必ず--uiモードで差分を確認します
トラブルシューティング
-
エラー:
Cannot access 'mockData' before initialization -
原因:
vi.mock()の外部で定義された変数は、ファクトリーから参照できません(巻き上げ) -
解決策:共有モック状態をトップレベルで定義するために、
vi.hoisted()で囲みます -
エラー:モックハンドラーが呼び出されず、実際の HTTP リクエストが送信される
-
原因:MSW サーバーが起動していないか、ハンドラーメソッドが間違っています(http と graphql)
-
解決策:
beforeAll()でserver.listen()を呼び出し、ハンドラーの HTTP メソッドがリクエストと一致していることを確認します -
エラー:ローカルではテストに成功するのに、CI では失敗する
-
原因:テスト間でフェイクタイマーがリセットされず、テストスイート全体で時刻がずれていきます
-
解決策:必ず
afterEach()でvi.useRealTimers()を呼び出します