vitest-unit-testing について
vitest-unit-testingは、既存プロジェクトでVitestを使った焦点の明確なTypeScript単体テストを書くためのスキルです。観測可能な契約の検証、プロジェクトの規約、適切な環境と実行コマンドの選択を重視します。
主な機能
- 01プロジェクトのテスト設定確認
- 02焦点を絞ったテスト境界の選択
- 03AAAによる独立したテスト構成
- 04モックと後処理の管理
- 05対象を絞ったVitest実行
活用シーン
- 01ユーティリティの回帰テスト追加
- 02サービスやAPIクライアントの動作検証
- 03テストファイルの実行環境選択
- 04不安定なテストの調査
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ perdolique/ workflow --skill vitest-unit-testingインストール後、Claude Code で/vitest-unit-testingを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
evals/evals.jsonevals/files/performance.mdevals/files/unit-project/package.jsonvitest.config.tsevals/files/unit-project/src/browser-storage.tsfee.tsguests.tspreferences.tstotal.tsevals/files/unit-project/src/__tests__/fee.test.tspreferences.test.tstotal.test.tsreferences/mocking.mdperformance.md詳細
Vitest によるユニットテスト
Vitest 5 を使って、対象を絞った TypeScript のユニットテストを作成します。観測可能な契約をテストし、各テストを独立させ、対象プロジェクトで確立されている規約に従ってください。
プロジェクトの状況を把握する
テストを編集する前に、対象プロジェクトの以下の点を確認してください。
- Vitest のバージョンとサポート対象の Node.js バージョン
- パッケージスクリプト、テストルート、設定ファイル、名前付きプロジェクト
- Node、happy-dom、jsdom、Browser Mode などのテスト環境と、各テストで読み込まれるセットアップファイル
clearMocks、mockReset、restoreMocksを含むクリーンアップ設定- プロジェクト内での命名、ファイルの配置、フィクスチャ、ヘルパー、アサーションのスタイル
このスキルの対象は Vitest 5 です。プロジェクトで古いバージョンを使用している場合は、API とデフォルト設定を調整してください。テストの変更依頼だけを理由に、依存関係をアップグレードしてはいけません。
テスト境界と環境を選ぶ
- このスキルは、ユーティリティ、サービス、ストア、変換処理、API クライアントの TypeScript ユニットテストと、それらのテストで使用するモックやフィクスチャに使用します。テストツールは、タスクとプロジェクトの既存設定に基づいて選んでください。モックやフィクスチャに関する一般的な依頼だけでは、使用するツールは決まりません。
- 観測可能な契約と、テストで検出するべき妥当な不具合を明確にします。ケースを追加する前に、近くにあるテストを確認してください。関連する判断を実行する、最小の公開境界を選びます。純粋関数は直接呼び出し、状態や連携先が契約を構成する場合はストアやサービスを使います。レンダリングやコンポーネントの操作が重要な場合は、コンポーネントをマウントします。
- テスト対象の判断に関わるモジュールは実物を使います。たとえば、保存済みの宿泊者の年齢をもとに料金をテストする場合は、実際の年齢から人数への計算処理が必要です。その人数をモックで渡しても、そのルールのテストにはなりません。保護対象の判断の外にある連携先をモックします。テストは独立かつ決定的に保ってください。
- テスト、その推移的なインポート、セットアップでブラウザー API が不要なら、Node を使います。プロジェクトの環境規約に従ってください。ファイル単位の
// @vitest-environment nodeを指定すれば、ほかのファイルを変更せずに DOM のセットアップを避けられます。契約に必要な場合は、適切な DOM またはブラウザー環境を維持してください。 - ブラウザーテストでは、ここで扱う計算以外のブラウザー固有のリスクをテストする必要があります。たとえば、レンダリング結果、リクエストの配線、フォーカス、ナビゲーションをまたいだ永続化などです。そのテストは、責務を持つ境界に置いてください。
テストの配置と命名
プロジェクトの既存の構成に従ってください。より強い規約がない場合は、次のようにします。
- テストは隣接する
__tests__/ディレクトリに配置します。 - 各ファイルは、ソースファイルの名前に
.test.tsを付けた名前にします。たとえば、config.tsに対して__tests__/config.test.tsとします。 - 関連する動作を
describeでグループ化し、各テスト名には具体的な結果を記述します。
AAA でテストを構成する
すべてのテストを、明確な Arrange、Act、Assert のセクションで構成します。
import { describe, expect, test } from 'vitest';
import { calculateTotal } from '../calculate-total';
describe(calculateTotal, () => {
test('returns the total price for all item quantities', () => {
// Arrange
const items = [
{ price: 100, quantity: 2 },
{ price: 50, quantity: 1 }
];
// Act
const total = calculateTotal(items);
// Assert
expect(total).toBe(250);
});
});
同じ契約が複数の入力に適用される場合は、test.each を使います。
test.each([
['production', 'https://app.example.com'],
['staging', 'https://staging.example.com'],
['development', 'http://localhost:3000']
])('returns the base URL for %s', (environment, expected) => {
const url = getBaseUrl(environment);
expect(url).toBe(expected);
});
契約ケースを選ぶ
- 正常な動作と、異なる契約上のリスクを防ぐエラー、境界、または限界ケースをテストします。既存のテストで同じ不具合を検出できる場合、ソース内の分岐ごとにケースを追加しないでください。外部データとの境界など、コードが入力の検証を担う場合は、
null、undefined、空の値、無効な型を含めます。検証済みの値を受け取る内部の型付きコードでは、サポートされている入力を使い、サポート対象外のケースを作り出さないでください。 - 有用な置き換えテストは、保護対象の動作が削除された場合に失敗します。各テストには、アサーションヘルパーを介する場合も含めて、結果を確認するアサーションを少なくとも 1 つ設けてください。契約を表現する場合は、
toBe、toStrictEqual、toHaveLength、toHaveBeenCalledWith、toHaveBeenCalledTimesなどの厳密なアサーションを優先します。
意図的なモックとクリーンアップ
モジュールモック、スパイ、条件付きの動作、タイマー、非同期エラー、クリーンアップについては、モックガイドをお読みください。
Vitest 5 では、clearMocks のデフォルト値は true です。そのため、モックの実装は保持されたまま、各テストの前に呼び出し履歴がクリアされます。mockReset と restoreMocks のデフォルト値は false です。
現在有効な設定を確認し、テストが変更する状態に必要なクリーンアップだけを追加してください。
-
テストで変更した実装を後続のテストに引き継がせないようにするには、モックをリセットします。
-
restoreMocksが無効の場合は、手動で作成したvi.spyOnのスパイを復元します。 -
テストまたはテストスイートでフェイクタイマーを使用した後は、実際のタイマーに戻します。
-
ホイストされる
vi.mock、vi.unmock、vi.hoistedの呼び出しは、モジュールレベルに配置します。Vitest 5 では、これらの呼び出しを関数、ブロック、フック、テストまたはテストスイートのコールバック内に置くとエラーになります。後続の動的インポートでホイストされない動作が必要な場合に限り、vi.doMockまたはvi.doUnmockを使用します。
非同期の動作を処理する
resolves、rejects、expect.poll、非同期スナップショットマッチャーを含む、非同期アサーションはすべて await します。Vitest 5 では、await されていない非同期アサーションは失敗します。
タイマーのコールバックがプロミスをスケジュールする場合は、非同期のタイマー制御を使用します。
await vi.advanceTimersByTimeAsync(1_000);
タイマーが拒否を発生させる場合は、時間を進める前に拒否のアサーションを作成し、その後、両方の処理を await します。これにより、プロミスが確定する前に拒否ハンドラーが登録されます。
TypeScript のチェックを有用に保つ
- モック関数に型安全にアクセスするには、
vi.mocked()を使用します。 - リテラル型を拡大せずに、フィクスチャや期待するペイロードを既知のコントラクトと照合するには、
satisfiesを使用します。 - ランタイム検証を確認するために、テストで意図的に無効な型を渡す場合は、
@ts-expect-errorを使用します。 - 部分モジュールファクトリーには、型付きの
vi.mock(import(...))シグネチャを使用します。エクスポートは省略可能で、返される型も引き続きチェックされます。
関連するテストを実行する
ユニットテストに適したコマンドが定義されている場合は、対象プロジェクトのパッケージスクリプトを使用します。Vitest は、設定を所有するプロジェクトのルートから非対話モードで実行してください。適切なスクリプトがない場合は、パッケージを直接 vpx vitest run で実行します。
# Project script, with a focused file when the script forwards arguments
pnpm run test:unit -- src/utils/__tests__/config.test.ts
# Direct package execution from the root that owns the config
vpx vitest run src/utils/__tests__/config.test.ts --config ./vitest.config.ts --project unit
- 変更したコントラクトと、それに関連するモックやフィクスチャを対象にするファイル、ディレクトリ、または名前付きプロジェクトを選択します。変更がほかのテストに影響する可能性がある場合は、実行範囲を広げます。Vitest 5 は親ディレクトリの設定を検索しないため、正しいルートから実行するか、
--configを明示的に指定し、必要に応じて検出範囲を限定してください。 - カバレッジの証拠が必要なタスクでは、カバレッジを使用します。不安定なテストの疑いを調べるには、
--repeatsを使用します。
テストのパフォーマンスを最適化する
タスクがテストの実行時間、ワーカーやメモリの設定、共通セットアップのコストを対象とする場合は、パフォーマンスガイドをお読みください。通常のテスト変更では、上記の関連する検証を行ってください。繰り返し比較する実行は、パフォーマンス調査に含まれます。
参考ファイル
- references/mocking.md — モジュールモック、スパイ、戻り値の動作、タイマー、クリーンアップ、アサーション、一般的な依存関係のパターン
- references/performance.md — セットアップコストの特定、実行時間設定の比較、時間とリソース使用量の測定