unit-test-vue-pinia
Vue 3 + TypeScript + Vitest + Pinia 構成のコードベースに対してユニットテストの作成・レビューを行います。コンポーネント・コンポーザブル・ストアのテスト新規作成や更新、`createTestingPinia` を用いた Pinia のモック化、Vue Test Utils のパターン適用、実装詳細ではなくブラックボックスアサーションの徹底が必要な場面で活用してください。
description の原文を見る
Write and review unit tests for Vue 3 + TypeScript + Vitest + Pinia codebases. Use when creating or updating tests for components, composables, and stores; mocking Pinia with createTestingPinia; applying Vue Test Utils patterns; and enforcing black-box assertions over implementation details.
SKILL.md 本文
unit-test-vue-pinia
このスキルを使用して、Vue コンポーネント、コンポーザブル、Pinia ストアのユニットテストを作成または確認します。テストは小さく、決定的で、動作重視に保ちます。
ワークフロー
- まず動作の境界を特定します:コンポーネント UI の動作、コンポーザブルの動作、またはストアの動作。
- その動作を証明できる最も狭いテストスタイルを選択します。
- シナリオをカバーしながら最小限の強力さで Pinia をセットアップします。
- props、フォーム更新、ボタンクリック、子コンポーネントの発行イベント、ストア API などの公開入力を通じてテストを駆動します。
- インスタンスレベルのアサーションを検討する前に、観察可能な出力とサイドエフェクトをアサートします。
- 動作指向の明確な名前を持つテストを返すか確認し、残りのカバレッジギャップについて記録します。
コアルール
- テストごとに 1 つの動作をテストします。
- 観察可能な入出力動作を最初にアサートします(レンダリングされたテキスト、発行されたイベント、コールバック呼び出し、ストア状態の変化)。
- 実装に依存したアサーションを避けます。
- DOM、prop、emit、またはストアレベルのアサーションで十分な理由がない例外的な場合を除き、
wrapper.vmにアクセスしません。 beforeEach()で明示的なセットアップを優先し、すべてのテストでモックをリセットします。references/pinia-patterns.mdのチェックイン済み参考資料を、標準的な Pinia テストセットアップの局所的な信頼できる情報源として使用します。
Pinia テストアプローチ
最初に references/pinia-patterns.md を使用し、チェックイン済みの例ではケースをカバーしていない場合は Pinia のテストクックブックにフォールバックします。
コンポーネントテストのデフォルトパターン
マウント時にグローバルプラグインとして createTestingPinia を使用します。
一貫性と更に簡単なアクション スパイ アサーションのため、createSpy: vi.fn をデフォルトとして優先します。
const wrapper = mount(ComponentUnderTest, {
global: {
plugins: [
createTestingPinia({
createSpy: vi.fn,
}),
],
},
});
デフォルトでは、アクションはスタブ化され、スパイされます。
テストがアクションが呼び出されたかどうかを検証するだけで良い場合は、stubActions: true(デフォルト)を使用します。
受け入れられた最小限の Pinia セットアップ
以下も有効であり、不正なものとしてフラグを立てるべきではありません:
createTestingPinia({})テストが Pinia アクション スパイ動作をアサートしない場合。createTestingPinia({ initialState: ... })またはcreateTestingPinia({ stubActions: ... })createSpyなし。テストは状態シーディングまたはアクション スタブ動作のみが必要で、生成されたスパイを検査しない場合。- ストア/コンポーザブル重視のテスト(コンポーネントをマウントしない)で、
setActivePinia(createTestingPinia(...))依存するストアのモック/シーディングが必要な場合。
アクション スパイ アサーションがテスト意図の一部である場合は createSpy: vi.fn を使用します。
必要な場合のみ実際のアクションを実行
stubActions: false は、テストがアクションの実際の動作とサイドエフェクトを検証する必要がある場合のみ使用します。単純な「呼び出されたか」アサーションのためにデフォルトでオンに切り替えないでください。
const wrapper = mount(ComponentUnderTest, {
global: {
plugins: [
createTestingPinia({
createSpy: vi.fn,
stubActions: false,
}),
],
},
});
initialState でストア状態をシード
const wrapper = mount(ComponentUnderTest, {
global: {
plugins: [
createTestingPinia({
createSpy: vi.fn,
initialState: {
counter: { n: 20 },
user: { name: "Leia Organa" },
},
}),
],
},
});
createTestingPinia を通じて Pinia プラグインを追加
const wrapper = mount(ComponentUnderTest, {
global: {
plugins: [
createTestingPinia({
createSpy: vi.fn,
plugins: [myPiniaPlugin],
}),
],
},
});
エッジケースのためのゲッターオーバーライドパターン
const pinia = createTestingPinia({ createSpy: vi.fn });
const store = useCounterStore(pinia);
store.double = 999;
// @ts-expect-error test-only reset of overridden getter
store.double = undefined;
純粋なストアユニットテスト
コンポーネントレンダリングなしでストア状態遷移とアクション動作を検証することが目標の場合は、createPinia() を使用した純粋なストアテストを優先します。スタブ化された依存ストア、シード済みテスト ダブル、またはアクション スパイが必要な場合のみ createTestingPinia() を使用します。
beforeEach(() => {
setActivePinia(createPinia());
});
it("increments", () => {
const counter = useCounterStore();
counter.increment();
expect(counter.n).toBe(1);
});
Vue Test Utils アプローチ
Vue Test Utils ガイダンスに従います:https://test-utils.vuejs.org/guide/
- フォーカスされたユニットテストのデフォルトでは浅くマウントします。
- 統合動作が対象の場合のみ、完全なコンポーネントツリーをマウントします。
- props、ユーザー的相互作用、発行されたイベントを通じて動作を駆動します。
- 親内部に接触する代わりに、子スタブイベントに
findComponent(...).vm.$emit(...)を優先します。 - 更新が非同期の場合のみ
nextTickを使用します。 wrapper.emitted(...)で発行されたイベントとペイロードをアサートします。- DOM アサーション、発行されたイベント アサーション、prop アサーション、またはストアレベル のアサーションで動作を表現できない場合のみ
wrapper.vmにアクセスします。これを例外として扱い、アサーションを狭くスコープします。
キーテストスニペット
イベントを発行してペイロードをアサート:
await wrapper.find("button").trigger("click");
expect(wrapper.emitted("submit")?.[0]?.[0]).toBe("Mango Mission");
入力を更新して出力をアサート:
await wrapper.find("input").setValue("Agent Violet");
await wrapper.find("form").trigger("submit");
expect(wrapper.emitted("save")?.[0]?.[0]).toBe("Agent Violet");
テスト作成ワークフロー
- テストするための動作境界を特定します。
- その動作に必要なフィールドのみを含む最小限のフィクスチャデータを構築します。
- Pinia と必要なテスト ダブルを構成します。
- 公開入力を通じて動作をトリガーします。
- 公開出力とサイドエフェクトをアサートします。
- テスト名をリファクタリングして、実装ではなく動作を説明します。
制約とセーフティ
- プライベート/内部実装の詳細をテストしません。
- 動的 UI 動作のためにスナップショットを過剰使用しません。
- 1 つの動作のみが重要な場合は、大きなオブジェクト内のすべてのフィールドをアサートしません。
- 偽データは決定的に保ち、ランダム値を避けます。
- Pinia セットアップが上記の受け入れられた最小限のセットアップの 1 つである場合、それが間違っていると主張しません。
- テスト対象の動作がその追加のサーフェスエリアを必要としない限り、より深いマウントまたは実際のアクションに向けて作業中のテストを書き直しません。
- レビュー中に、欠落しているテストカバレッジ、脆い選択肢、実装に依存したアサーションを明示的にフラグを立てます。
出力契約
createまたはupdateの場合、完成したテストコードと選択された Pinia 戦略を説明する短いメモを返します。reviewの場合、具体的な調査結果を最初に返し、その後欠落しているカバレッジまたは脆性リスクを返します。- 最も安全な選択が曖昧な場合は、選択されたテストセットアップを駆動した仮定を述べます。
参考資料
references/pinia-patterns.md- Pinia テストクックブック:https://pinia.vuejs.org/cookbook/testing.html
- Vue Test Utils ガイド:https://test-utils.vuejs.org/guide/
ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ
詳細情報
- 作者
- github
- ライセンス
- MIT
- 最終更新
- 不明
Source: https://github.com/github/awesome-copilot / ライセンス: MIT
関連スキル
doubt-driven-development
重要な判断はすべて、本番環境への展開前に新しい視点から対抗的レビューを実施します。速度より正確性が重要な場合、不慣れなコードを扱う場合、本番環境・セキュリティに関わるロジック・取り消し不可の操作など影響度が高い場合、または後でバグを修正するよりも今検証する方が効率的な場合に活用してください。
apprun-skills
TypeScriptを使用したAppRunアプリケーションのMVU設計に関する総合的なガイダンスが得られます。コンポーネントパターン、イベントハンドリング、状態管理(非同期ジェネレータを含む)、パラメータと保護機能を備えたルーティング・ナビゲーション、vistestを使用したテストに対応しています。AppRunコンポーネントの設計・レビュー、ルートの配線、状態フローの管理、AppRunテストの作成時に活用してください。
desloppify
コードベースのヘルスチェックと技術負債の追跡ツールです。コード品質、技術負債、デッドコード、大規模ファイル、ゴッドクラス、重複関数、コードスメル、命名規則の問題、インポートサイクル、結合度の問題についてユーザーが質問した場合に使用してください。また、ヘルススコアの確認、次の改善項目の提案、クリーンアップ計画の作成をリクエストされた際にも対応します。29言語に対応しています。
debugging-and-error-recovery
テストが失敗したり、ビルドが壊れたり、動作が期待と異なったり、予期しないエラーが発生したりした場合に、体系的な根本原因デバッグをガイドします。推測ではなく、根本原因を見つけて修正するための体系的なアプローチが必要な場合に使用してください。
test-driven-development
テスト駆動開発により実装を進めます。ロジックの実装、バグの修正、動作の変更など、あらゆる場面で活用できます。コードが正常に動作することを証明する必要がある場合、バグ報告を受けた場合、既存機能を修正する予定がある場合に使用してください。
incremental-implementation
変更を段階的に実施します。複数のファイルに影響する機能や変更を実装する場合に使用してください。大量のコードを一度に書こうとしている場合や、タスクが一度では完結できないほど大きい場合に活用します。