バックエンド実装時に使用。DRY原則遵守。コーディング規約準拠。
test-design
実装前に呼ぶ。High/Medium リスク変更のテストオラクル(期待値の根拠)とファルシフィケーション項目を定義する。
インストール方法を見る含まれるファイル(1)
- SKILL.md16.9 KB
SKILL.md(原文)
インストールする前に、エージェントに与えられる指示の中身を確認できます。
Test Design Skill - テストオラクル起点のテスト設計
目的
テストコードを書けることと、正しいテストオラクルを設計できることは別能力である。
実装した AI 自身がテストを書くと、実装を通すことが目的化し(リワードハッキング)、実装の誤りをテストが一緒に間違える相関故障が起きる。テストの Green は「書いたテストの範囲で期待どおりに動いた」ことしか意味せず、期待値そのものが誤っていれば Green は誤りを追認するだけになる。
本スキルは、実装コードを書く前に「何が壊れうるか」「期待値の根拠はどこにあるか」「どうすればこの実装が間違っていることを証明できるか」を文書化し、実装と検証を同じ最適化ループから引き剥がす。
原則の定義は documents/development/quality-policy.md §4「テストオラクル原則」を正とする(本スキルはその実行手順である)。
実行タイミング
writing-plans / TDD(テストコードの作成)の手前で実行する。実装コードもテストコードも書き始める前が唯一の正しいタイミングであり、実装後に書いたメモはオラクルの独立性を担保しない。
- 機能実装・バグ修正のプランを立てた直後、最初のテストを書く前
quality-checkStep 3 から遡及実行された場合(後述「quality-check Step 3 との接続」)
Step 0: 適用判定(リスクレベルの自己判定)
変更予定の内容から、documents/development/quality-policy.md §1 のリスクレベル定義に照らして自己判定する。判定基準の表は同 §1 を参照すること(ここには転記しない)。
判定ルール:
- 複数領域にまたがる場合は最も高いレベルを採用する
- 判定に迷う場合は1段階高いレベルに倒す
| 判定結果 | 本スキルの適用 |
|---|---|
| High | 必須 — 以降の Step 1〜5 を実施し、テスト設計メモを作成する |
| Medium | 必須 — 同上 |
| Low | 対象外 — メモは不要。そのまま実装・TDD に進んでよい |
ゲート強度の全体像は documents/development/quality-policy.md §2 のゲートマトリクスを参照する。
判定結果(レベルとその根拠)はメモの冒頭に記録し、quality-check Step 1 のリスク判定と突き合わせられるようにする。
成果物: テスト設計メモ
保存先と命名規則
docs/superpowers/plans/YYYY-MM-DD-<feature>-test-design.md
YYYY-MM-DD: メモ作成日<feature>: 対象機能のスラッグ(対応するプランがある場合はプランと同じスラッグを使う)- 例:
docs/superpowers/plans/2026-08-20-order-cancellation-test-design.md
ライフサイクルはプランと同じ(非コミット)。 docs/superpowers/ は .gitignore 済みのローカル作業領域であり、メモをコミットしてはならない。
この命名規則は仕様である。
quality-checkStep 3 はテスト設計メモをdocs/superpowers/plans/*-test-design.mdのグロブで発見し、レポートスキーマのtest_design.memo_pathにそのパスを記録する。命名規則から外れたパスに置いたメモは発見されず、メモ欠落として遡及実行の対象になる。
Step 1: この変更の最重要リスク(上位3つ)
「この変更が本番で壊れたとき、何が最も痛いか」を列挙し、影響度で上位3つに絞る。
- ビジネス影響(金銭・データ喪失・信頼失墜)と発生しやすさの両面で評価する
- 「テストしやすいから」ではなく「壊れたら痛いから」で選ぶ
- 3つに絞ることが目的である。網羅リストではなく優先順位付けの結果を書く
Step 2: 保証すべき状態遷移・不変条件
この変更が守らなければならない「常に真であるべきこと」を、検証可能な文として書く。
- 状態遷移: 許される遷移と許されない遷移(例:
キャンセル済から発送済への遷移を許さない) - 不変条件: 処理の前後で崩れてはならない性質(例: 二重処理を許さない境界 — 同一リクエスト ID の再送で残高が二重に減らない、在庫合計が負にならない、集計値と明細の合計が一致する)
- 「〜が正しく動く」のような検証不能な文は不可。違反を観測できる形で書く
Step 3: Failure Mode → テスト層のマッピング
Step 1・2 で挙げたリスクと不変条件を Failure Mode カテゴリに分類し、各カテゴリに対応するテスト層を選ぶ。
対応表は documents/development/quality-policy.md §3「テスト層選択の原則(テストトロフィー)」を参照して選ぶ。表を本メモに転記してはならない(二重管理を避けるため。参照した行の Failure Mode 名を書けばよい)。
原則:
- テストの本数ではなく、Failure Mode に対して最も適切な層を選ぶ
- カバレッジ率は下限であって、テスト十分性の証明ではない
- 上位層(E2E)で捕まえられるからといって、下位層で捕まえるべきものを上位層に押し上げない
Step 4: テストオラクル定義(本スキルの中核)
各テストについて、期待値がどこから来たのかを明示する。
オラクル(期待値の根拠)として認められるもの:
- 仕様書・要件定義・受け入れ条件の該当箇所(節番号まで特定する)
- 計算根拠(数式・税率・丸め規則など、実装とは独立に導出できるもの)
- 外部仕様・プロトコル定義・API 契約
- 手計算・別手段での独立導出(表計算での検算など)
禁止事項:
-
実装の出力をそのまま期待値にすること。 実装を動かして得られた値をコピーして期待値に据える行為は、実装の誤りをテストが追認する構造そのものであり、検証として無効である
-
スナップショットの無検証な更新。 差分の中身を仕様に照らして確認せずに snapshot を更新することは、上と同じ構造である
-
実装と同一のロジックを再実装して期待値を生成すること(同じ誤りを両方が犯す)
-
HTTP ステータスの期待値は、対象ルートで登録順に先に効くガード(
bodyLimitの 413・Content-Type の 415・CSRF の 403・認証の 401 等)を、実装のミドルウェア登録順で確認してから書く。ガードの順序自体が仕様なら、§2(不変条件)の行として残す(#147) -
TZ に依存するテストは
vi.stubEnvではなく、プロセスの起動前にprocess.env.TZ(vitest のenv設定)で固定する
根拠が特定できない期待値が出てきた場合、それは仕様が未定であるというシグナルである。実装で埋めない(実装から逆算しない)。まず設計・要件・機能ドキュメントから導く。導けないときは、設計の目的に最も沿う期待値を選び、根拠欄に「設計に記載なし(設計との差異として報告)」と書いて、設計との差異に記録する(documents/development/development-policy.md §1.0「承認後の進め方」)。設計の承認後はユーザーに途中で確認しない。設計の目的に照らしても期待値を選べない重要な製品判断なら、X4(差異の設計を 1 通で示す)に当たる。
ミューテーションが担保しない変更種別(#121)
PIT / Stryker などのミュータント生成器は、catch の例外型の絞り込み / 拡張、throws 宣言、例外のラップ型、型パラメータなど、一部の構文を変異させない。これらの変更行はミューテーションテストで撃殺率に反映されず、Step 5(quality-check)の生存台帳にも載らない。
- 絞り込む catch ごとに、「対象の例外は従来どおり握られる」と「対象外の実行時例外は伝播する」の両側オラクルを必須項目とする(片側だけでは
return 0相当の実装と区別できない) - これらは撃殺を主張しないテストである旨を本メモに書く(quality-check Step 3-2 のメモ照合で確認される)
Step 5: ファルシフィケーション項目
「この実装が正しいことを確認する」のではなく、「この実装が間違っていることを証明する」ための入力・シナリオ候補を挙げる。
考える切り口:
- 境界値とその外側(ゼロ・負値・null・空・最大値・オーバーフロー・精度の限界)
- 不正な順序での操作(Step 2 で禁止した遷移をそのまま実行する)
- 並行・再送・リトライ(同時実行、同一リクエストの二重送信、途中失敗後の再試行)
- 外部依存の異常系(タイムアウト、5xx、不正なレスポンス、時刻のずれ、乱数の偏り)
- 権限の越境(他ユーザーのリソース、権限のないロール、認証切れ)
- 実装が「たまたま通る」入力(すべて同じ値、1件だけ、ソート済みの入力など、偶然一致してしまうケース)
挙げた項目は Step 3 で選んだ層のテストに落とし込む。落とし込まなかった項目は、その理由をメモに残す(実施しない判断も記録の対象である)。
この観点は quality-check Step 4 の QAエンジニア(ファルシフィケーション型)と対になっている。メモの本項目が薄いと、Step 4 で同じ指摘を受けて手戻りする。
メモのテンプレート
以下をそのままコピーして使う。
# テスト設計メモ: <機能名>
- 日付: YYYY-MM-DD
- 対象: <対象の変更範囲・関連プラン>
- リスクレベル: High | Medium (判定根拠: quality-policy §1 のどの基準に該当するか)
## 1. この変更の最重要リスク(上位3つ)
| # | リスク | 影響 |
|---|---|---|
| 1 | 決済の二重課金 | 顧客への過剰請求・返金対応・信頼失墜 |
| 2 | キャンセル済み注文の再処理 | 在庫と売上の不整合 |
| 3 | 外部決済 API のタイムアウト時に注文だけ確定する | 未決済の出荷 |
## 2. 保証すべき状態遷移・不変条件
- 不変条件: 同一の冪等キーで複数回リクエストされても、決済は1回しか実行されない(二重処理を許さない境界 = 決済実行の直前)
- 状態遷移: `キャンセル済` から `発送済` への遷移は常に拒否される
- 不変条件: 注文合計金額 = 明細金額の合計 + 送料 - 割引(処理の前後で常に成立)
## 3. Failure Mode → テスト層のマッピング
> 対応表は quality-policy.md §3 を参照(転記しない)
| Failure Mode(§3 の分類) | 対象 | 選んだ層 | 理由 |
|---|---|---|---|
| 状態遷移・不変条件 | 注文ステータス遷移 | ユニット + 統合 | 遷移制約は純粋関数で、永続化後の状態は DB 観測が必要 |
| 並行・リトライ・冪等性 | 冪等キーによる決済 | 統合 | DB の一意制約込みでないと二重実行を再現できない |
| 外部依存 | 決済 API の失敗 | 統合(スタブ境界) | タイムアウト・5xx を注入して分岐を観測する |
## 4. テストオラクル定義
| テスト | 期待値 | 期待値の根拠(オラクル) |
|---|---|---|
| 割引適用後の請求額 | 8,800円 | 要件定義 §3.2「10%割引・税込表示・端数切り捨て」より 9,800 × 0.9 = 8,820 → 端数規則適用で 8,800(手計算で独立導出) |
| 二重リクエスト時の決済回数 | 1回 | 仕様書 §5.1「冪等キーが一致する再送は初回結果を返す」 |
| 決済 API タイムアウト時の注文状態 | `保留` | 仕様書 §5.4 の状態遷移図(`確定` にしてはならない) |
| (ミューテーション非対象の例)`DataAccessException` のみ握り他の `RuntimeException` は伝播する | 対象例外: 握って再試行 / 対象外: 伝播 | 仕様書 §6.1(両側オラクル。撃殺を主張しない担保 — #121) |
**禁止事項の確認**: 上記の期待値はいずれも実装の出力から取得していない。根拠が特定できなかった項目:
- (なし / もしくは「〇〇の丸め規則が仕様に未定義 → 設計の目的から △△ を採用(設計との差異として報告)」)
## 5. ファルシフィケーション項目
「この実装が間違っていることを証明する」ための入力・シナリオ候補。
| # | シナリオ | 狙う誤り | 落とし込み先 |
|---|---|---|---|
| 1 | 同一冪等キーで同時に2リクエスト | 排他が甘く二重決済する | 統合テスト(並行実行) |
| 2 | 割引率100% / 金額0円 | ゼロ除算・負値の請求 | ユニットテスト(境界値) |
| 3 | 決済 API が成功レスポンス後にタイムアウト | 決済済みなのに注文が保留のまま孤立 | 統合テスト(スタブ) |
| 4 | キャンセル直後に発送処理 | 遷移チェックの抜け | ユニット + 統合 |
**実施しない項目とその理由**:
- (例: #5 は対象外の決済手段でのみ発生するため今回のスコープ外)
quality-check Step 3 との接続
quality-check Step 3 は High / Medium リスクの変更に対し、テスト設計メモの存在と、テストがメモの項目(特に Step 4 のオラクルと Step 5 のファルシフィケーション項目)を満たしているかを照合する。
メモが存在しない場合、quality-check はエラーにしない。 次の遡及ルールに従う。
- その場で本スキルを遡及実行し、テスト設計メモを作成する
- 作成したメモと既存テストとの差分(不足テスト)を洗い出す
- 不足テストを補完する
- 補完後に先へ進む
遡及実行時の注意:
- メモは既存の実装コードやテストコードからではなく、仕様・要件から書き起こす。実装を読んで期待値を写せば、遡及実行の意味そのものが失われる(Step 4 の禁止事項がそのまま適用される)
- 洗い出した不足テストは、Step 5 のファルシフィケーション項目を優先して補完する
verified を名乗れるのは、メモの作成が対象実装の最初のコミットより前であることを確認できた場合のみであり、確認できないときは retroactive に倒す。
ミューテーションテスト(test-recommendation スキル)との接続: ミューテーションを実施した場合、本メモの「保証すべき状態遷移・不変条件」(Step 2)と「ファルシフィケーション項目」(Step 5)に対応する変更行で生存したミュータントは memo_linked: true として台帳に載り、優先して対処される(test-recommendation スキル「通過判定なし — 生存の対処は既定の規則で決める」)。この2項目が具体的であるほど、生存ミュータントのうち「優先的に対処すべきもの」が機械的に特定できる。
照合結果は .quality-check-report.json の test_design(memo_path を含む)に記録される。フィールド定義は skills/project/_schemas/quality-check-report.schema.md を参照する。
完了条件
- リスクレベルを自己判定した(quality-policy §1。複数領域は最高レベル / 迷ったら1段階高く)
- Low リスクではない(Low ならメモ不要でここで終了)
- メモを
docs/superpowers/plans/YYYY-MM-DD-<feature>-test-design.mdに作成した(非コミット) - 5項目すべてを記入した(最重要リスク上位3 / 状態遷移・不変条件 / Failure Mode → テスト層 / テストオラクル定義 / ファルシフィケーション項目)
- 各期待値に実装以外の根拠(仕様書・要件・計算根拠)を明記した
- 根拠が特定できない期待値を、設計・要件から導くか、設計の目的に沿って選び設計との差異に記録した(あった場合)
- Failure Mode → テスト層は quality-policy §3 を参照して選んだ(表の転記をしていない)
- 実装コード・テストコードを書く前にここまで完了している
レビュー
まだレビューはありません。使ってみた感想をお寄せください。
同じリポジトリのスキル
概要と使いどころ
Use before implementing any feature, behavior change, or refactor - settles requirements and design, then gets the design independently reviewed and approved by the user before code is written
日本語の概要は準備中です。原文の説明を表示しています。
作業開始時に使用。mainブランチでの作業禁止。Issue先行作成必須。
UI実装後の検証時に使用。agent-browser CLIでブラウザ上の動作を手動検証する。「UIを確認」「画面テスト」と言われたら使用(プロジェクトの E2E スイート実行は quality-check Step 5(推奨度・範囲で自動実施または確認)/ server-startup が担当)。
DBマイグレーション作成時に使用。バージョン番号競合防止。mainブランチ確認必須。
Use when independent tasks benefit from parallel work without shared state or sequential dependencies
日本語の概要は準備中です。原文の説明を表示しています。