mcpField
A
ai-qa-review

ai-qa-review

github.com/petrkindlmannテスト・品質2221.2k 回インストール6 日前に更新
リポジトリ

ai-qa-review について

ai-qa-reviewは、テストの品質、アプリケーションコードのテスト容易性、カバレッジの不足を調べるQA向けコードレビュースキルです。テストのにおいを分類し、根拠・影響・修正案を含む指摘を促します。

主な機能

  1. 01テストのにおいとアサーション品質の確認
  2. 02アプリケーションコードのテスト容易性分析
  3. 03境界値や異常系の不足検出
  4. 04PR変更またはテストスイート全体のレビュー
  5. 05lint・ミューテーションゲートの提案

活用シーン

  1. 01PRで追加・変更されたテストのレビュー
  2. 02テストスイートに共通する問題の監査
  3. 03テストしにくいアプリケーションコードの調査

インストール

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

$npx skills add https://github.com/petrkindlmann/qa-skills --skill ai-qa-review

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

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
mutation-testing.md
smell-examples.md
testability-refactors.md

詳細

テストの匂いを検出し、アプリケーションコードのテスト容易性を分析して、カバレッジの不足を特定する、QA に特化したコードレビューです。`toBe(true)` をアサートするテストも、正常系の入力だけを与えるカバレッジ 95% のテストスイートも、どちらも問題がないように見えますが、どちらもバグを隠しています。このスキルでは、匂いに名前を付け、該当行を示し、「問題なさそう」という状態をミューテーションスコアのゲートに変えます。

開始前: プロジェクトのルートに .agents/qa-project-context.md があるか確認してください。このファイルには、テストフレームワークの規約、命名パターン、プロジェクト固有の品質基準が記載されており、レビューのフィードバックを調整するのに役立ちます。


クイックルート

入口は 3 つあります。該当する行を選び、指定されたセクションに進んでください。

状況ルート移動先
テストファイルに変更がある PR変更されたファイルを実行してスコアを算出し、PR チェックリストに照らして差分を確認する検証 → PR レビューチェックリスト
テストスイート全体の健全性を確認したい定量化してサンプルを調べ、全体に見られる 3~5 件の匂いを見つけ、Lint/ミューテーションのゲートを提案する一括監査プロセス
アプリケーションコードを見て、「なぜテストしにくいのか?」を確認したいDI/副作用/純粋関数/インターフェースの問題を、修正前後の例とともに指摘するテスト容易性の分析

3 つのルートはすべて、同じ匂いの語彙(以下の 6 つの分類)と同じ検証コマンドを使用します。


確認事項

まず .agents/qa-project-context.md があれば読み、すでに回答されている質問は飛ばしてください。

  1. レビュー範囲: テストコードの品質、アプリケーションコードのテスト容易性、またはその両方をレビューしますか?それぞれ、クイックルートの異なる経路に進みます。
  2. フレームワークの規約: どのテストフレームワークを使っていますか(Jest、Vitest、Playwright、pytest など)?describe/it のネスト、フィクスチャの使い方、アサーションのスタイルなどの規約はフレームワークによって異なり、検証コマンドもフレームワークごとに異なります。
  3. PR レビューと一括監査のどちらですか? PR レビューでは変更されたファイルだけを実行してスコアを算出します。一括監査では、テストスイート全体をスキャンして全体的な傾向を調べます。
  4. 既存の品質基準: チームで文書化されたテスト規約はありますか?.eslintrc のテストルール、CONTRIBUTING.md のテストガイドライン、テストスタイルガイドを確認してください。
  5. 既知の問題: 繰り返し発生する不安定なテスト、遅いテストスイート、分かりにくい失敗などはありますか?これらをもとに、優先して確認する匂いを決めます。

基本原則

  1. テストコードもプロダクションコードです。 可読性、保守性、単一責任など、同じ品質基準を適用してください。読みづらいテストコードは信頼しにくいものです。

  2. 実行された内容だけでなく、アサートされた内容をレビューしてください。 カバレッジから分かるのは行が実行されたことだけで、誤った値を検出できるかどうかは分かりません。toBeTruthy アサーションだけのカバレッジ 95% のテストスイートでは、ほとんど何も検出できません。ミューテーションスコア(検証を参照)は、カバレッジでは測れないものを測定します。

  3. テスト容易性のレビューでテスト負債を防ぎます。 アプリケーションコードのテスト容易性をレビューすれば、扱いにくいテスト上の回避策が必要になる前に、設計上の問題を見つけられます。テストしにくいコードは、たいてい保守もしにくいものです。

  4. 知識だけでなくパターンを定式化してください。 繰り返し指摘する内容を、Lint ルール、カスタム ESLint プラグイン、共有フィクスチャに変えましょう。同じフィードバックを繰り返すレビューは、自動化が不足していることを示しています。

  5. 匂いは症状であり、最終判断ではありません。 テストの匂いは潜在的な問題を示しますが、実際に有害かどうかは状況によります。複雑なワークフローをテストする長いテストは適切な場合があります。境界をテストするためにモックを多用するのも、正しい場合があります。

  6. 実行可能なフィードバックだけを提供してください。 各レビューコメントには、何が問題か、なぜ重要か、どう直せばよいかを含めてください。「このテストはよくありません」では実行に移せません。「このテストは sleep に基づいて待機するため不安定になります。明示的な待機条件に置き換えてください」なら実行に移せます。


テストの匂いの分類

6 つの観点があります。それぞれの匂いは、影響する観点に分類され、具体的なレビューアクションにリンクされています。カタログ化されたすべての匂いの完全な SMELL/FIX コードは references/smell-examples.md にあります。本文中の参照は目立つようにしてください。修正前後のコードが要となる部分です。

可読性に関するスメル

一目で理解しにくいテストにつながる問題です。

分かりにくいセットアップ

見た目: 無関係なフィールドがテストの意図を覆い隠す、30行以上にわたるオブジェクトの構築です。読み手には、アサーションに関係するフィールドがどれなのか分かりません。

修正方法: ファクトリーに切り出します。テスト本文には、テストに関係するデータだけを記述します。ユーザー/商品/注文の完全なオブジェクトをその場で構築する代わりに、buildOrder({ items: [buildItem({ weight: 2.5, quantity: 2 })] }) を使います。

レビューでの対応: ファクトリーへの切り出しを求めます。

ミステリーゲスト

見た目: loadFixture('report.json') のように、読み手には見えない外部データにテストが依存しています。アサーションを理解するには、別のファイルを開く必要があります。

修正方法: テストに関係するデータをインラインで記述するか、内容が分かる名前のフィクスチャを使います。読み手がほかのファイルを開かずにテストを理解できるようにします。

レビューでの対応: データのインライン化、または内容が分かるフィクスチャ名を求めます。

重複したアサーション

見た目: 複数のテストが、具体性を変えながら同じ動作をアサートしています(toBe('Alice')、toHaveProperty('name')、toBeDefined())。テストは3つでも、動作は1つです。

レビューでの対応: 統合を求めます。最も具体的なアサーションを残します。冗長なテストは、信頼性を高めずに保守コストを増やします。


信頼性に関するスメル

テストが断続的に失敗したり、想定外の環境で失敗したりする問題です。

スリープによる待機

見た目: 同期のために setTimeout、sleep()、waitForTimeout() を使用しています。SMELL/FIX の例は references/smell-examples.md を参照してください(waitForTimeout を toBeVisible による明示的な待機に置き換えます)。

レビューでの対応: 却下します。スリープによる待機は決して許容されません。明示的な待機条件を必須とします。

実行順序への依存

見た目: テストをまとめて実行すると成功するものの、単独で実行した場合や異なる順序で実行した場合に失敗します。SMELL/FIX の例は references/smell-examples.md を参照してください(各テストで独自の前提条件を作成します)。

レビューでの対応: データの分離を求めます。各テストで独自の前提条件を作成する必要があります。

外部サービスとの結合

見た目: テストが実際の外部 API(決済ゲートウェイ、メールプロバイダー、サードパーティーサービス)を呼び出しています。SMELL/FIX の例は references/smell-examples.md を参照してください(サービス境界をモックします)。

レビューでの対応: サービス境界でのモックまたはフェイクを求めます。外部呼び出しは、ユニットテストではなく統合テスト/コントラクトテストで行います。


診断に関するスメル

テストの失敗を理解してデバッグしにくくする問題です。

情報量の少ないアサーションメッセージ

見た目: 何が期待されていたのか、なぜ失敗したのかが分からないままアサーションが失敗します。SMELL/FIX の例は references/smell-examples.md を参照してください(toBe(true) を、問題の値が分かる expect(result.errors).toEqual([]) のような具体的なアサーションに置き換えます)。

レビューでの対応: 診断に役立つ、より強いアサーションを求めます。失敗メッセージだけで問題が説明され、テストのソースを読む必要がないようにします。

1つのテストに複数の失敗原因がある

見た目: 1つのテストが、互いに独立した複数の動作を対象にしています。失敗したとき、どの動作が壊れたのか分かりません。SMELL/FIX の例は references/smell-examples.md を参照してください(ライフサイクルテストを、テストごとに1つの動作を検証する形に分割します)。

レビューでの対応: テストの分割を求めます。各テストには、失敗する理由が1つだけあるようにします。


設計に関するスメル

テストアーキテクチャにおける、保守コストを増やす問題です。

条件付きテストロジック

見た目: テスト本文内に if/else、switch、三項演算子、または for ループがあります。テスト内の分岐ロジック自体はテストされていないため、どのケースが実際に実行されたのか分かりません。SMELL/FIX の例は references/smell-examples.md を参照してください(分岐のあるループを it.each に置き換えます)。

レビューでの対応: パラメーター化テスト(it.each/test.each)を求めます。テスト内の条件付きロジックは、実際に検証されているケースを見えにくくします。

巨大なフィクスチャ

どのようなものか: 各テストで使うのは2〜3個なのに、すべてのテストで20個以上のオブジェクトをセットアップする beforeEach やフィクスチャです。references/smell-examples.md のSMELL/FIXペア(モノリシックな beforeEach を、テストごとのインラインセットアップに置き換える例)を参照してください。

レビュー時の対応: インラインセットアップを求めます。共有セットアップは、モノリシックな beforeEach ブロックではなくファクトリーに移します。

過剰なモック

どのようなものか: 単純な値オブジェクトや純粋関数も含め、すべての協調オブジェクトがモック化されています。references/smell-examples.md のSMELL/FIXペア(テスト対象の関数自体のモックを取り除く例)を参照してください。

レビュー時の対応: 不要なモックの削除を求めます。内部ではなく、境界をモック化します。


AI生成テストのにおい

テストコードがコーディングエージェント(Claude Code、Codex、Cursor、Copilot)によって作成された場合も、においの分類は同じです。ただし、特徴的な失敗が繰り返し頻繁に起こるため、個別に確認する価値があります。

におい検出方法
幻覚によるロケーター実際のページで一度テストを実行します。ロケーターが一度も一致しない場合、LLMが存在しない data-testid を作り出しています。
捏造されたインポートインポートされたシンボルをすべて静的チェックし、そのファイルまたはパッケージが実際にエクスポートしているか確認します。LLMはもっともらしいAPI(@testing-library/something-that-doesnt-exist)を作り出します。
汎用的なテストデータexample.com、[email protected]、Lorem ipsum、John Doe — エージェントがプロジェクト固有のファクトリーを知らないために生成した定型データです。プロジェクトのデータファクトリーに置き換えます。
閉じたAIループ同じセッションで、実装とテストの両方を同じエージェントが作成しています。テストはエージェントが作ったものを説明しているだけで、制約を与えていません。エージェントのテストに、人間が作成した境界テストを少なくとも1つ組み合わせるか、shift-left-testing に従ってTDD(テストファースト)を使用します。ミューテーションスコアの低さ(検証を参照)が客観的な判断材料になります。
プロジェクト規約からの逸脱Page Object、フィクスチャ、命名、またはアサーションのスタイルが、テストスイートの他の部分と異なっています。AI生成コードは、ローカルの規約に最初から合致することはほとんどありません。

初めてテストを生成する際のパターンとStep-7のレビューチェックリストについては、ai-test-generation に相互リンクしてください。AIシステムの評価スイート(プロンプト用のESLintに相当するもの)については、各ツールのCLIランナー — promptfoo eval、deepeval test run(Apache 2.0)、Ragasの ragas evaluate / experiments(Apache 2.0) — を、テストランナーと並行して品質ゲートとして組み込みます。

Promptfooの所有権に関する注記: PromptfooはOpenAIに買収されました(2026年3月9日発表)。コアはMITライセンスのオープンソースで、モデルに依存しない状態が維持されます。レッドチーム機能はOpenAI Frontierに統合される予定です。promptfoo eval は引き続き適切な品質ゲートコマンドです — 今後はベンダーがOpenAIになることを想定してください。

カバレッジのにおい

検証対象に抜けが生じる問題です。

ハッピーパスのみ

どのようなものか: すべてのテストで有効な入力を渡し、成功を期待しています。エラーパスはテストされていません。references/smell-examples.md のSMELL/FIXペア(割引計算機にゼロ、最大値、負の値、境界値のケースを追加する例)を参照してください。

レビュー時の対応: 不足しているシナリオを求めます。BOUNDARYフレームワークを使います:境界値、Null/空、重複、順序、範囲の上限。

境界ケースの不足

どのようなものか: 「通常」の値(5項目)はテストしているものの、0、1、最大値、または最大値+1はテストしていません。境界を明示的に網羅するために it.each を使います:空のコレクション、単一項目、ページサイズちょうど、1件超過、大きなセット。

レビュー時の対応: 境界テストを求めます。数値パラメーター、文字列の長さ、コレクションのサイズには、それぞれテストすべき境界があります。

エラー/異常ケースの不足

どのようなものか: 問題が起きたときの動作をテストしていません — ネットワーク障害、無効な入力、権限拒否、同時変更などです。

レビュー時の対応: ハッピーパスの各テストについて、「対応する失敗モードは何か」と問いかけます。その失敗をテストするよう求めます。

テスト容易性の分析

アプリケーションコードをレビューする際は、テストしやすい構造になっているかを評価してください。各小節には、references/testability-refactors.md にテストしにくい例とテストしやすい例の変更前/変更後が記載されています。

依存性注入

依存関係を直接インスタンス化しているクラス(メソッド内の new PostgresDatabase()、new StripeClient() など)を指摘してください。テストでモックやフェイクに置き換えられるよう、コンストラクターインジェクションを提案してください。references/testability-refactors.md を参照してください。

副作用の分離

純粋な計算と I/O(メール、ロギング、分析)を混在させている関数を指摘してください。計算を純粋関数として切り出し、副作用を伴うオーケストレーターから呼び出してください。references/testability-refactors.md の calcTotal の変更前/変更後を参照してください。

純粋関数の抽出

リクエストハンドラーの中に埋め込まれた、検証、変換、ビジネスルールを探してください。ロジックが app.post('/api/orders', ...) にインラインで記述されている場合、HTTP サーバーを起動せずに単体テストすることはできません。独立した関数として切り出してください。references/testability-refactors.md の shippingFor の変更前/変更後を参照してください。

インターフェース分離

使用するメソッドが2~3個だけなのに、(PrismaClient 全体のような)広範なインターフェースに依存しているクラスを指摘してください。実際に使用するメソッドだけを持つ狭いインターフェースを提案してください。これにより、テストダブルを簡単に実装できます。references/testability-refactors.md を参照してください。


レビューワークフロー

PR レビューチェックリスト

PR 内の各テストファイルについて、次の項目を体系的に確認してください。

## Test Quality Review

### Readability
- [ ] Can I understand what each test verifies in under 10 seconds?
- [ ] Is setup minimal and test-relevant?
- [ ] Are test names descriptive: "should [behavior] when [condition]"?

### Reliability
- [ ] No sleep/waitForTimeout/setTimeout for synchronization?
- [ ] No shared mutable state between tests?
- [ ] No dependency on test execution order?
- [ ] No calls to real external services?

### Diagnostic Value
- [ ] Will failures produce messages that identify the problem?
- [ ] Does each test have one reason to fail?
- [ ] Are assertions specific (not toBeTruthy/toBeDefined)?

### Design
- [ ] No conditional logic (if/else/switch/for) in test bodies?
- [ ] Fixtures/setup proportional to what each test needs?
- [ ] Mocking limited to external boundaries?
- [ ] Parameterized tests (it.each) used for data-driven scenarios?

### AI-Generated (if applicable)
- [ ] Locators verified against a real page (no hallucinated data-testid)?
- [ ] Imports resolve (no fabricated APIs)?
- [ ] Project data factory used, not [email protected] / John Doe?

### Coverage
- [ ] Happy path AND error/negative paths tested?
- [ ] Boundary values tested (0, 1, max, max+1)?
- [ ] Edge cases: empty, null, duplicate, concurrent?
一括監査プロセス

テストスイート全体を監査する場合:

  1. 定量化: テストを種類(単体/統合/E2E)、フレームワーク、ディレクトリごとに数えます。
  2. サンプリング: テストファイルの10~20%をレビューします。特に、サイズが大きいものや最近変更されたものを優先します。
  3. パターンの特定: サンプル全体で最もよく見られる問題を3~5個特定します。
  4. 優先順位付け: 影響度に基づいて順位を付けます。信頼性に関する問題 > 診断に関する問題 > 設計に関する問題 > 可読性に関する問題。
  5. 自動化: よくある問題ごとに、ESLint ルールまたはミューテーションスコアのゲートで自動検出できるかを判断します。
  6. 報告: 具体例、修正案、重大度(高/中/低)、推定工数を含めて、調査結果を記録します(レビューしたファイルごとに1行)。

プロンプトテンプレート

AI を活用したレビュー向けの3つのプロンプトパターン:

  1. テスト品質のレビュー: 「このテストファイルについて、可読性、信頼性、診断、設計、AI 生成、カバレッジに関する問題を確認してください。各問題について、問題の名称、該当行、重要である理由、修正案を示してください。」

  2. カバレッジの不足箇所を特定: 「このアプリケーションコードと既存のテストをもとに、正常系、エラー処理、境界値、エッジケース、並行処理、セキュリティに関する不足シナリオを特定してください。P0/P1/P2 の優先順位を付けてください。」

  3. テスト容易性の改善: 「このアプリケーションコードについて、ハードコードされた依存関係、混在する副作用、抽出可能な純粋関数、広範すぎるインターフェースを確認してください。現在のコードとリファクタリング後のコードを示してください。」


アンチパターン

  1. 本番コードの基準だけでテストコードをレビューする。 テストコードには、本番コード用リンターではチェックされない、信頼性、診断、カバレッジという追加の品質面があります。「クリーンコード」の原則だけでなく、6つのテスト臭の分類を適用してください。

  2. 文脈を考慮せず、あらゆるテスト臭を指摘する。 複雑な状態機械をテストする50行のテストは、分かりにくいセットアップではなく、必要な複雑さです。テスト対象の振る舞いに照らして、テスト臭を評価してください。

  3. あらゆるものにモックを提案する。 過剰なモック自体がテスト臭です。純粋関数、値オブジェクト、高速なプロセス内の依存先をモックすることは推奨しないでください。モックを使うのは、ネットワーク、データベース、ファイルシステム、クロックなどの境界にしてください。

  4. カバレッジの質よりカバレッジ率を重視する。 正常系のテストしかない95%の行カバレッジは、エラー経路や境界値を含む75%のカバレッジより劣ります。実行された行だけでなく、何がアサートされているかをレビューし、ミューテーションスコアで裏付けてください。

  5. 実行せずにレビューする。 静的解析では実行時の問題を見逃します。テストスイートを実行し(検証を参照)、繰り返し実行して不安定さを確認し、実行時間もチェックしてください。20分かかる合格済みのテストスイートには、パフォーマンス上の問題があります。

  6. 一度きりのレビューで、フォローアップしない。 テストの品質は時間とともに低下します。定期的なレビューの実施間隔を設定するか、回帰を検出する自動品質ゲート(リンタールール、ミューテーションのしきい値)を設けてください。


検証

コメントを始める前に実行してください。これらは、このスキルが必須としている実行時チェックを具体化したものです。PRレビューではPRで変更されたテストファイルを対象にし、一括監査ではテストスイート全体を実行してください。

  1. テストスイートを一度実行する。 レビュー前にすべて成功していることを確認してください。失敗したテストやスキップされたテストを、成功したかのようにレビューしてはいけません。
    • Vitest:npx vitest run <files> · Jest:npx jest <files> · Playwright:npx playwright test <files> · pytest:pytest <files>
  2. 繰り返し実行して不安定さを見つける。 一度は成功し、次の実行では失敗するテストは、偶然の問題ではなく信頼性に関するテスト臭です。
    • Vitest:npx vitest run --retry=0 <files>をループ実行するか、for i in 1 2 3; do npx vitest run <files> || break; done
    • Jest:npx jest <files> && npx jest <files> && npx jest <files>(またはjest-circusで繰り返し実行)
    • Playwright:npx playwright test --repeat-each=3 <files>
    • pytest:pytest --count=3 <files>(pytest-repeat)を実行するか、順序依存を検出するためにランダムな順序とpytest -p no:randomlyを比較する
  3. テストごとの実行時間を記録する。 20分かかるテストスイートには、パフォーマンス上の問題があります。
    • Vitest:--reporter=verbose(テストごとの実行時間を出力) · Jest:--verbose · Playwright:--reporter=list · pytest:--durations=10
  4. ミューテーションスコア — 客観的な最後の確認項目。 大規模には目視で確認できない定性的なテスト臭(閉じたAIループ、弱いアサーション)については、ミューテーション実行ツールを実行し、スコアを確認してください。ミューテーションスコアが約60%未満のAI生成テストでは、実装に十分な制約をかけられません。ツール一式、しきい値、設定についてはreferences/mutation-testing.mdを参照してください。
    • JS/TS:npx stryker run · Java:PIT mvn ... mutationCoverage · Rust:cargo mutants · Python:mutmut run

手順1〜3の出力とミューテーションスコアが、レポート内のすべての「信頼性」または「診断」に関する指摘の根拠になります。


完了条件

  • 指摘事項の成果物にレビュー対象のファイルごとに1行があり、各行に重大度(高/中/低)が記載されています。(ファイルが存在し、行数 == レビューしたファイル数)
  • レビュー対象のコードに当てはまる、すべてのコードスメルの観点が網羅されています。可読性、信頼性、診断性、設計、AI 生成、カバレッジです。(レポートに6つの見出しがあり、「該当なし」は可、空欄は不可)
  • 重大度が高い各指摘事項に、説明だけでなく、実行可能な修正手順(何をするか+理由+修正方法)が記載されています。
  • 検証を実施済みです。テストスイートを少なくとも3回実行してすべて成功しており(不安定な失敗なし)、テストごとの実行時間も記録されています。AI 生成テストスイートの場合は、ミューテーションスコアも記録されています。
  • 少なくとも1つの繰り返し発生するコードスメルが、自動ゲート(ESLint ルール、CI チェック、コミット済みのミューテーションスコアしきい値)に変換されています。または、レポートに自動ゲートが不要であると明記されています。

参照ファイル(references/ 内)

  • smell-examples.md — 信頼性、診断性、設計、カバレッジの各観点で、カタログに掲載されているすべてのコードスメルについて、SMELL/FIX のコード例を掲載しています。
  • testability-refactors.md — テスト容易性に関する4つの小項目すべてについて、テストが難しいコードとテスト可能なコードの変更前/変更後を掲載しています。依存性注入、副作用の分離、純粋関数の抽出、インターフェース分離です。
  • mutation-testing.md — ツール(Stryker/PIT/cargo-mutants/mutmut)、しきい値、Stryker の設定、AI ループ/アサーションの弱さに対するゲートについて説明しています。

関連スキル

  • unit-testing — 各フレームワークで「適切」な状態を判断するための、フレームワーク固有のパターン(Jest、Vitest、pytest)です。
  • shift-left-testing — レビュー前にテストスメルを検出する、コミット前フックと IDE 連携です。
  • coverage-analysis — カバレッジレポートを解釈し、単なる割合の目標ではなく、意味のある不足箇所を見つけます。
  • ai-test-generation — 生成されたテストにもレビューが必要です。AI 生成テストコードにも、これらのコードスメルのチェックを適用してください。
  • test-reliability — 信頼性に関するコードスメル(sleep による待機、実行順序への依存)は、不安定なテストのパターンと重複します。

コメント