crucible は何をしますか?
使用すべき場面
TypeScript プロジェクトでユニットテストの作成、修正、または監査を依頼された場合。
使用すべきでない場面
エンドツーエンドテスト、統合テスト、UIテスト、またはシミュレーションテストを作成する場合。
プロジェクト単位のオプトアウト
アクティベートする前に、プロジェクトがこのスキルをオプトアウトしているか確認してください。以下のいずれかを探します。
- プロジェクトルートに
.no-crucibleファイルが存在する AGENTS.mdまたは.claude/settings.jsonのいずれかに"crucible": falseが含まれている
オプトアウトのシグナルが見つかった場合、自動でアクティベートせず、この会話でユーザーが明示的にリクエストした場合にのみ適用してください。
ルール
- 例示コマンドでは
pnpmを使用しますが、常にプロジェクトのパッケージマネージャーを使用してください。 - 明示的に促されない限り、アプリケーションコードを変更しないでください。
- テスト追加を依頼された場合、既存のテストを変更しないでください。
- テスト修正を依頼された場合、新しいテストを追加しないでください。
- テスト監査を依頼された場合、既存のテストを修正し、その後テスト基準を満たすために必要に応じてテストを追加してください。
テスト基準
ユニットテストは以下を満たす必要があります。
- Vitest で可能な最大のブランチカバレッジを持つこと。
- プロンプトのスコープ内の全コード(テストでカバーされている範囲だけでなく)に対して、可能な最大のミューテーションスコアを達成し、殺せるミュータントをすべて殺すこと。殺せないミュータントはスコア100を阻みます。
- 可能な限りプロパティベーステストであること。ただし、入力ケースがごくわずかしかない場合を除きます。例:単一のブール値パラメータと暗黙的な入力を持たない関数の場合、入力ケースは2つしかないため、プロパティベーステストにする必要はありません。
- (プロパティベーステストの場合)すべてのパラメータと暗黙的な入力をカバーするアービトラリーを持つこと。本番環境で発生しうるケースが除外されないことが重要です。必要であれば、または不明瞭な場合は、アービトラリーを過度に広く設定するようにしてください。
- 誤ったコードをテストする場合や、アービトラリーが意図的に広すぎる場合に失敗すること。テストを要件として考えてください。それに応じて名前を付け、ユーザーが将来バグを修正した後(関数やアービトラリーを修正した後)に自動的にパスするようにしてください。
test.fails/.skipは使用しないでください。これらはユーザーに注意が必要であることをわかりにくくするため、テストがパスすべきでないときにパスすることは、最も優先度の高いエラーとして回避すべきです。
ブランチカバレッジを確認し、テストを実行:pnpm exec vitest run src/foo.test.ts --coverage
テスト対象コードの生存ミュータントを確認:pnpm exec stryker run --mutate "src/foo.ts"
テスト設定の確認
- 以下のパッケージがすべてプロジェクトにインストールされていることを確認します:
vitest fast-check @stryker-mutator/core @stryker-mutator/vitest-runner @stryker-mutator/typescript-checker - Vitest と Stryker の設定が正しくファイルを包含/除外していることを確認します。Stryker はテストデータのみを含むファイルをチェックすべきではありません。
- Stryker 設定を確認します:
clear-textレポーターを使用していること(他のレポーターはオプション)。- TypeScript チェッカーを使用し、TS設定ファイルを正しく指していること。
- テスト作成ワークフローに問題を引き起こす可能性のある、その他の設定上の問題がないか確認します。
- 結果をユーザーに報告します。
テストの作成
新しいテストを作成するよう依頼された場合、アプリケーションコードや既存のテストを変更しないでください。
まず、モジュールの評価に従って既存のテストを評価します。テンプレートを使用して新しいデブリーフファイルを作成し、初期のカバレッジとミューテーションスコアを記録します。
次に、以下のプロセスに厳密に従ってテストを作成します:
モジュールのインターフェースにある各関数/メソッドについて、1つの関数を完了してから次の関数に進むまで、以下を行います。
- 関数の目的を、コメント、名前、型シグネチャ、および使用方法を調べて判断します。不明な場合は、デブリーフにその旨を記録し、テスト作成をスキップして次の関数に進みます。
- 関数の実装における潜在的なバグを記録します。
- 目的に基づいて、関数がそのパラメータと暗黙的な入力について行っている誤った仮定を特定し、誤った関数動作につながりそうな入力ケースを記録します。例えば、正の整数を受け取るが入力を検証しない関数は、入力について誤った仮定をしています。
- 既存のテストは絶対に変更しないでください。既存のテストに問題が見つかった場合は、ユーザーに通知します。
- 以下のように新しいテストを作成します:
a.
fast-checkを使用して、関数のすべてのパラメータと暗黙的な入力をカバーするアービトラリーを持つプロパティベーステストスタブを作成します。テスト対象の関数が非同期の場合はfc.asyncProperty+await fc.assert(...)を使用します。迷った場合は、アービトラリーを広くしすぎる方向に設定し、その旨をデブリーフに記述してユーザーが修正できるようにします。テストには望ましい動作の説明として名前を付けます。 b.vitestを使用して、スタブ内にアサーションを記述し、戻り値や副作用(例外のスロー、入力の変更、外部スコープの変数の変更/再代入など)をカバーします。テストが望ましい動作をアサートし、先に特定した誤った仮定やバグを捕捉して適切に失敗するようにします。 - カバレッジを再確認:
pnpm exec vitest run src/foo.test.ts --coverage - 現在の関数のみをミューテーションテスト:
pnpm exec stryker run --mutate "src/foo.ts:<開始行>-<終了行>" - 新しく作成したテストを修正し、関数のテスト基準(上記)が満たされるまで手順5aと5bを繰り返します。
- この関数に関するセクションをデブリーフに追加します。
すべての関数のテスト作成後、各関数のセクションがデブリーフに追加されていることを再確認し、サマリーセクションを完了してください。
テストの監査
プロジェクト全体の監査を求められた場合、プロジェクト全体のコードカバレッジとミューテーションスコアを確認し、より詳細な監査やテストの追加/更新を推奨する領域を提案します。推奨は、コードベースの中で最も重要でバグが発生しやすい領域(コアビジネスロジック、イベント駆動コード、複雑な関数)に偏らせてください。
プロジェクトの一部の監査を求められた場合、(プロンプトのスコープ内で)テストがないモジュールや関数を探し、監査後のデブリーフでユーザーに報告します。
プロンプトのスコープ内でテストがある各モジュールについて、モジュールの評価に従ってください。その後、評価修正後もテスト基準が満たされない場合は、テストの作成に従って残りのギャップを埋めます。
モジュールの評価
このプロセスは、新しいテストを作成する前と監査時の両方で、既存のテストファイルをテスト基準に対して評価する必要がある場合に使用します。
- Vitest を使用してコードカバレッジを確認:
pnpm exec vitest run src/foo.test.ts --coverage。 - Stryker Mutator を使用して生存ミュータントを確認:
pnpm exec stryker run --mutate "src/foo.ts"。 - テストがあるモジュール内の各関数について:
- プロパティベーステストの場合:
- 関数が例外をスローしたりエラー値を返したりせずに受け入れるが、アービトラリーでは生成できない入力を探します。そのような入力があれば、アービトラリーを広げます。
- アービトラリーでカバーされていない入力、特にクラスフィールド、グローバル変数、日付/時刻、ランダムに生成された数値などの暗黙的な入力を探します。これらに対するアービトラリーを追加します。
- モック実装のエラーを修正します。
- パフォーマンスのボトルネックを探します。
- プロパティベーステストの場合:
- カバレッジとミューテーションスコア、および発見事項をデブリーフに記録します。
テストデブリーフ
以下のテンプレートに従ってデブリーフをフォーマットします。関数のサブセクションで報告すべき内容がない場合は、単に「該当なし」と記述します。デブリーフは debriefs/ 内の Markdown ファイルに出力します。
デブリーフ:{モジュール名/ファイル名} {yyyy-mm-dd}
サマリー
カバレッジ(ブランチ) Before: X% → After: Y% カバーできなかった行:{行範囲}
ミューテーションスコア(合計) Before: X% → After: Y%
問題
{誤った仮定、見つかったバグ、テストの問題、失敗するテストの箇条書きリスト。各項目は、問題が見つかったファイルのプロジェクトルート相対パスと行番号で始める}
{関数名}
関数の目的 {関数が何をすることを意図しているかを一文で}(確信度:高 | 不確か) {不確かな場合:何が不明瞭でその理由}
見つかった誤った仮定
- (行{行番号/範囲}):{関数が検証していない入力の型/範囲/形状に関する仮定}
実装に見つかったバグ
- (行{行番号/範囲}):{説明 + 行番号}
既存のテストに見つかった問題
- (行{行番号/範囲}):{問題の説明 + テスト名}
作成したテストケース
- {テストした各プロパティ/不変条件の簡単な説明}
失敗するテスト
- (行{行番号/範囲}):{テスト名 + 理由}
殺せないミュータント
- (行{行番号/範囲}):{簡単な説明}