KoderKoder.ai
料金エンタープライズ教育投資家向け
ログインはじめる

プロダクト

料金エンタープライズ投資家向け

リソース

お問い合わせサポート教育ブログ

リーガル

プライバシーポリシー利用規約セキュリティ利用ポリシー不正利用を報告

ソーシャル

LinkedInTwitter
Koder.ai
言語

© 2026 Koder.ai. All rights reserved.

ホーム›ブログ›境界ケース向けのClaude Codeテスト生成プロンプト
2025年12月19日·1 分

境界ケース向けのClaude Codeテスト生成プロンプト

ハッピーパスではなく境界・インバリアント・障害モードを狙って高シグナルなテストを生む、Claude Code向けのテスト生成プロンプトを学ぶ。

境界ケース向けのClaude Codeテスト生成プロンプト

なぜハッピーパステストの自動生成は時間を無駄にするのか

自動生成されたテストスイートは見た目には豪華に見えます: 数十のテスト、膨大なセットアップコード、あらゆる関数名がどこかに登場します。しかし多くのテストは「普通に動けばOK」というチェックに過ぎません。簡単に通り、バグをほとんど検出せず、読むにも保守するにも時間がかかります。

典型的なClaude Codeのテスト生成プロンプトでは、モデルは与えられた例入力を写す傾向があります。見た目が違うだけのバリエーションが増え、同じ振る舞いだけをカバーする結果になります。結果として、重要な箇所の網羅が薄い大きなスイートが出来上がります。

高シグナルなテストは違います。少数でも先月のインシデントを検出していたであろうテストです。危険な方法で振る舞いが変わると失敗し、無害なリファクタでは安定します。高シグナルなテスト1件は「期待した値を返す」チェック20件に相当する場合があります。

低価値なハッピーパス生成にはいくつかの明確な兆候があります:

  • 多くのテストが入力ラベルだけで異なり、壊れうる点をカバーしていない。\n- アサーションが浅い(「nullでない」「ステータスが200」)だけで意味を確認していない。\n- セットアップがテスト対象の振る舞いより重く、人がテストを更新しなくなる。\n- カバレッジは高く見えるが、エッジケースは untouched のまま。

例えば割引コードを適用する関数を考えてみてください。ハッピーパスのテストは「SAVE10で価格が下がる」ことを確認します。本当のバグは別の場所に潜みます: 0や負の価格、期限切れコード、丸めの端、最大割引上限など。これらが合計金額を壊し、顧客の怒りや深夜のロールバックを引き起こします。

目標は「より多くのテスト」から「より良いテスト」へ移ることです。焦点は3つ: 境界、障害モード、インバリアント。

3つのターゲット: 境界、障害モード、インバリアント

高シグナルなユニットテストを得たいなら、「テストをもっとくれ」と要求するのをやめ、代わりに3種類のテストを要求してください。これが、Claude Codeのテスト生成プロンプトで有用なカバレッジを生むコアです。

1) 境界(バグが潜む場所)

境界はコードが受け入れる/生成する範囲の端です。多くの実際の欠陥はオフバイワン、空状態、タイムアウト問題で、ハッピーパスでは表に出ません。

最小値と最大値(0、1、最大長)、空か存在か(""、[]、nil)、オフバイワン(n-1、n、n+1)、時間制限(境界付近)を考えてください。

例: APIが「最大100アイテム」を受け入れるなら、3だけでなく100と101をテストします。

2) 障害モード(安全に失敗することを証明する)

障害モードはシステムの壊れ方です: 不正な入力、依存の欠落、部分結果、上流のエラーなど。良い障害モードテストはストレス下での振る舞いを確認し、理想条件での出力だけをチェックしません。

例: データベース呼び出しが失敗したとき、関数は明確なエラーを返し、部分的な書き込みを避けるか?

3) インバリアント(常に成り立つべきルール)

インバリアントは呼び出し前後で常に真であるべき事実です。あいまいな正しさを明確なアサーションに変えます。

例:

  • 引き出し後に残高が負にならないこと。\n- アイテムIDは高速に作成しても一意であること。\n- エラー時には状態が変わらないこと(新しい行が作られない、フラグが反転しない)。

これら3つを狙えばテストは少なくなりますが、それぞれがより多くのシグナルを持ちます。

準備: テストを書く前に小さな契約を抽出する

早すぎる段階でテストを要求すると、丁寧な「期待通り動く」チェックの山が返ってきます。簡単な対策は、まず小さな契約を書き、それからその契約からテストを生成することです。これがClaude Codeのテスト生成プロンプトを実際にバグを見つけるものに変える最速の方法です。

読み切れる長さに収めた契約を作りましょう。目安は5〜10行で、次の3つに答えます: 入力は何か、出力は何か、他に何が変わるか。

5–10行の契約テンプレート

契約はコードではなくプレーンな言葉で、テスト可能なことだけを含めてください。

  • 入力: 型、許容範囲、「空」や「欠如」の定義
  • 出力: 返り値やエラーの形、成功の保証とは何か
  • 副作用: 状態、DB行、ネットワーク呼び出し、ファイル、ログの変化
  • 想定: 呼び出し側がしばしば間違えやすいこと(タイムゾーン、エンコーディング、認可、順序)
  • 「決して起きてはならないこと」: クラッシュ、データの沈黙損失、二重課金、部分書き込み

それができたら、現実がどこで仮定を壊すかをスキャンしてください。そこが境界(最小/最大、ゼロ、オーバーフロー、空文字、重複)や障害モード(タイムアウト、権限拒否、一意制約違反、破損入力)になります。

具体例: reserveInventory(itemId, qty) のような機能を考えると、契約は qty が正の整数であること、関数はアトミックであること、在庫が負にならないことを含めるかもしれません。すると高シグナルテストはすぐに明らかになります: qty = 0、qty = 1、在庫より大きいqty、同時呼び出し、途中で強制的にDBエラーが発生した場合など。

Koder.aiのようなチャットベースのツールを使っている場合でも、ワークフローは同じです: まずチャットで契約を書き、その後で境界・障害・「決して起きてはならない」リストを直接攻撃するテストを生成します。

プロンプトパターン: 高シグナルテストの青写真

少ないテストでそれぞれが重みを持つセットを欲しいときは、このClaude Codeテスト生成プロンプトを使ってください。重要な一手はまずテスト計画を強制し、計画を承認してからテストコードを生成することです。

You are helping me write HIGH-SIGNAL unit tests.

Context
- Language/framework: <fill in>
- Function/module under test: <name + short description>
- Inputs: <types, ranges, constraints>
- Outputs: <types + meaning>
- Side effects/external calls: <db, network, clock, randomness>

Contract (keep it small)
1) Preconditions: <what must be true>
2) Postconditions: <what must be true after>
3) Error behavior: <how failures are surfaced>

Task
PHASE 1 (plan only, no code):
A) Propose 6-10 tests max. Do not include “happy path” unless it protects an invariant.
B) For each test, state: intent, setup, input, expected result, and WHY it is high-signal.
C) Invariants: list 3-5 invariants and how each will be asserted.
D) Boundary matrix: propose a small matrix of boundary values (min/max/empty/null/off-by-one/too-long/invalid enum).
E) Failure modes: list negative tests that prove safe behavior (no crash, no partial write, clear error).
Stop after PHASE 1 and ask for approval.

PHASE 2 (after approval):
Generate the actual test code with clear names and minimal mocks.

実用的なコツとして、境界マトリクスをコンパクトな表にすることを要求すると、抜けが明らかになります:

DimensionValid edgeJust outside“Weird” valueExpected behavior
length0-110,000error vs clamp vs accept

Claudeが20件のテストを提案したら突き返してください。類似ケースを統合して、本当にバグを見つけるものだけを残すように促します。

ステップバイステップ: プロンプトを実行して出力をテストに変える

ビルドとテストを一つのフローで
機能を作りながら境界と障害のテストを生成してビルドとテストを一つの流れにします。
プロジェクト開始

まず挙動の小さな具体的な契約で始めます。関数シグネチャ、入力と出力の短い説明、既存テスト(ハッピーパスだけでも)を貼り付けてください。これによりモデルはコードが実際に何をするかに基づいて出力し、推測に走りにくくなります。

次に、テストコードを要求する前にリスクテーブルを要求します。列は3つ必須: 境界ケース(有効入力の端)、障害モード(悪い入力、欠落データ、タイムアウト)、インバリアント(常に成り立つべきルール)。各行に「なぜこれが壊れるか」を1文付けてください。シンプルな表は多数のテストファイルよりもギャップを明らかにします。

その後、各テストが固有のバグ検出目的を持つ最小セットを選びます。2つのテストが同じ理由で失敗するなら、強い方だけを残します。

実用的な選択ルール:

  • 異なる境界を叩くテストを残す(最小、最大、空、オフバイワン)。
  • 障害時に安全な振る舞い(明確なエラー、部分書き込みなし、クラッシュしない)を証明するテストを残す。
  • インバリアントをアサートするテストを残す(順序、合計、冪等性、重複なし)。
  • 「普通の入力で動く」だけのテストは削る。

最後に、各テストに「失敗したらどんなバグを検出したか」を短く書くことを要求してください。その説明が漠然としている(「振る舞いを検証」)なら、そのテストはおそらく低シグナルです。

インバリアントをアサーションへ落とし込む方法

インバリアントは有効な入力であれば常に成り立つべきルールです。まずそれをプレーンな文に書き、その後にテストで証明できるアサーションに変換します。

守るべきインバリアントは通常、安全性(データ損失しない)、一貫性(同じ入力は同じ出力)、上限(上限を超えない)に関するものが良いです。

インバリアントを検証可能なチェックに変える手順

インバリアントを短い文に書き、それからテストで観測できる証拠(返り値、保存されたデータ、発行されたイベント、依存への呼び出し)を決めます。強いアサーションは結果と副作用の両方をチェックします。多くのバグは「OKを返したが、書き込みが間違っていた」ケースに隠れます。

例えばクーポンを注文に適用する関数があるとします:

  • インバリアント: 最終合計が負にならない。
  • インバリアント: 同じクーポンを2回適用しても2重割引されない。

これを具体的なアサーションに変えると:

expect(result.total).toBeGreaterThanOrEqual(0)
expect(db.getOrder(orderId).discountCents).toBe(originalDiscountCents)

「期待通りの結果を返す」などの漠然としたアサーションは避け、具体的なルール(非負)や副作用(割引が一度だけ適用されている)を確認してください。

テストをシャープに保つための反例メモを追加する

各インバリアントに対して、テスト内にそのインバリアントを破るデータの短い例をコメントとして書いておくとよいです。これによりテストが後でハッピーパスへと退化するのを防げます。

維持しやすいパターン:

  • テスト名にインバリアントを入れる。\n- 結果に対してインバリアントをアサートする。\n- 主要な副作用(あるいは副作用がないこと)をアサートする。\n- 破るケースの一文コメントを入れる(例: 極端に大きなクーポン値や重複適用)。

障害モード: 安全に失敗することを証明するテストを書く

高シグナルなテストはコードが安全に失敗することを確認するものです。モデルがハッピーパスしか書かない場合、依存関係や入力が乱れたときの挙動は分かりません。

まずその機能にとって「安全に失敗する」とは何かを定義してください。型付きエラーを返すのか、デフォルトにフォールバックするのか、一度だけ再試行して止めるのか。期待される振る舞いを一文で書き、それをテストで証明します。

Claude Codeに障害モードテストを求めるときは、目的を厳格にしてください: システムが壊れる方法を網羅し、期待する正確な応答をアサートさせます。便利な一文は: 「浅いテストの多数より、強いアサーションを持つ少数のテストを優先する」です。

良い障害カテゴリ:

  • 不正入力: フォーマット不正、必須フィールドの欠如、範囲外の値
  • 依存失敗: タイムアウト、500エラー、空応答、破損ペイロード
  • 順序問題: 順序外イベント、重複、部分書き込み
  • 同時性: 競合更新、冪等性チェック
  • リカバリ: エラーを返すのかフォールバックするのか再試行するのか

例: ユーザを作成しウェルカムメールサービスを呼ぶエンドポイントがあるとします。低価値なテストは「201が返る」をチェックするだけですが、高シグナルな障害テストはメールサービスがタイムアウトしたらユーザを作るか(201とemail_pendingフラグ)、あるいはユーザを作らずに503を返すか、どちらかの一貫した挙動をアサートします。応答と副作用の両方をチェックしてください。

また、何を漏らさないかもテストしてください。バリデーションが失敗したらDBに何も書かれないこと、依存が破損ペイロードを返しても未処理例外や生のスタックトレースを返さないことなどです。

低価値テストを生む一般的な罠

チームで振る舞いを揃える
同じワークスペースにメンバーを招いて、早期に契約とインバリアントで合意しましょう。
チームを招待

低価値なテストセットはモデルが量で報酬を得ると発生します。「20ユニットテストを出して」と要求すると、同じような小さな変化ばかりが増え、本質的なことをほとんど捉えません。

一般的な罠:

  • 似たようなテスト: 同じ「有効入力」テストを異なる文字列や数で繰り返す。\n- コードをそのまま反映するテスト: 観測可能な振る舞いではなくプライベートな手順やヘルパー呼び出しをアサートする。\n- 何でもモックする: DB、クロック、ネットワーク、設定をすべて置き換える。\n- 弱いアサーション: 「エラーなし」「nullでない」「ステータス200」だけを確認する。\n- 汚れた共有状態: シードデータを残す、グローバルを変更する、キャッシュを汚す。

例: 「ユーザ作成」関数。10のハッピーパステストはメール文字列を変えるだけで、重複メール拒否、空のパスワード処理、返されるユーザIDの一意性など重要な点を見逃します。

レビュでのガードレール:

  • 各テストがカバーするリスク(境界・障害モード・インバリアント)を名前で示すことを要求する。\n- 実装のみを検証するチェックは避ける。\n- モックは最小限にし、実際の統合ポイントに当たる小さな数のテストを許容する。\n- 強いアサーションを要求する: 正確な出力、状態変化、エラーの型/メッセージ。\n- テストが順序に依存しないようクリーンアップルールを追加する。

例: 1つの機能を小さく強いテストセットに変える

想定機能: チェックアウトでクーポンコードを適用する。

契約(小さくテスト可能に): カートの小計(セント)とオプションのクーポンを受け取り、最終合計(セント)を返す。ルール: パーセントクーポンは最も近いセントに切り捨て、固定クーポンは固定額を差し引き、合計は0より小さくならない。クーポンは無効・期限切れ・既使用の可能性がある。

「applyCoupon()のテストを作って」と頼むのではなく、この契約に紐づいた境界、障害モード、インバリアントを要求してください。

エッジ動作を強制する境界

数学や検証を壊しやすい入力を選びます: 空のクーポン文字列、小計=0、最低購入額の直前と直後、固定割引が小計を上回るケース、33%のような丸めを生むパーセント。

安全な振る舞いを証明する障害モード

クーポン検索が失敗したり状態が間違っていることを想定します: クーポンサービスがダウン、クーポンが期限切れ、既にこのユーザが使っている。テストはその後に何が起きるか(クーポン拒否と明確なエラー、合計は変わらない等)を証明します。

最小で高シグナルなテストセット(5件)とそれぞれが捕らえるもの:

  • 空または空白のみのコードを拒否: 空文字を有効として受け入れるバグやトリミングの不備を捕らえる。\n- パーセントの丸め(subtotal 101、33%): 丸め間違いやオフバイワンのセントを捕らえる。\n- 固定割引が小計を上回る(subtotal 500、discount 1000): 合計が負にならないというインバリアントを証明する。\n- 最低購入額の境界(subtotal 999 vs 1000): 比較演算子の誤り(< と <=)を捕らえる。\n- クーポン検索の失敗やタイムアウト: フォールバック(割引を適用しない)と安定したエラー処理を証明する。

これらが通れば、重複したハッピーパステストでスイートを埋めることなく、一般的な破綻点をカバーできます。

高シグナルなAI生成テストのためのクイックチェックリスト

生成の前に計画を立てる
まず明確な契約とテストマトリクスを作成し、それから自信を持ってコードを生成します。
プランを使う

生成物を受け入れる前に簡易品質チェックを行ってください。目的は、それぞれのテストが特定で起こり得るバグからあなたを守ることです。

このチェックリストを合格ゲートに使います:

  • 入力ごとの境界: 文字列、ID、タイムスタンプ、フラグ等それぞれに少なくとも1つのエッジケース(空と空白のみ、最大長、0と負値、必須フィールドの欠如、制限を1つ超えた値)。\n- 依存失敗: 依存が誤動作した場合のテストを少なくとも1つ含める(DBタイムアウト、サードパーティAPIの500、期限切れトークン)。安全に失敗することを証明する(明確なエラー、部分書き込みなし)。\n- 強いアサーションのインバリアント: 1–3個の必須ルールを選び、それを直接アサートする。曖昧な「response is ok」は避ける。\n- テストごとにユニークなバグ: 各テスト名を読んで「これが失敗したらどのバグを捕まえるか?」と問う。二つが同じ問いに答えるなら統合する。\n- 削除テスト: テストを削除しても重要な境界・障害・インバリアントが失われないなら、そのテストは不要。

生成後の実用的なコツ: テスト名を「should <振る舞い> when <境界条件>」や「should not <悪い結果> when <障害>」にリネームしてください。きれいにリネームできないなら、それは焦点が甘い証拠です。

Koder.aiで開発するなら、このサイクルはスナップショットとロールバックと相性が良い: テストを生成して実行し、ノイズが増えたらロールバックして高シグナルセットを安定させます。

次のステップ: 再利用可能なワークフローにする

このプロンプトを一回限りのものとせず、再利用可能なハーネスとして扱ってください。境界、障害モード、インバリアントを強制する青写真プロンプトを保存し、関数やエンドポイント、UIフローごとに使い回します。

すぐに結果を上げる小さな習慣: 各テストについて「このテストが失敗したらどのバグを捕らえるか」を1文で書かせること。もしその文が一般的なら、そのテストはノイズです。

ドメインのインバリアント一覧を持っておくこと。頭の中に入れずに記録しましょう。実際のバグを見つけるたびに追加してください。

繰り返し可能な軽量ワークフロー:

  • 小さな契約を抜き出す: 入力、出力、エラーハンドリング、3–5のインバリアント。\n- 青写真プロンプトを走らせ、境界、障害、インバリアントと1行の正当化を要求する。\n- 異なるリスクをカバーする上位5–10件だけを実装する。\n- リファクタし、変化したリスクを把握するためにプロンプトを再実行する。\n- 重複を削り、過去のインシデントを検出していたテストだけを残す。

チャットでアプリを構築する場合は、契約、計画、生成されたテストが同じ場所にあるようKoder.ai(koder.ai)内でこのサイクルを回してください。リファクタで不意に振る舞いが変わったらスナップショットとロールバックで比較し、安定するまで反復します。

よくある質問

関数ごとにどれくらいのユニットテストを生成すべきですか?

デフォルト: 実際のバグを見つけられる小さなセットを目標にしてください。

手早く決めるなら 関数/モジュールあたり6–10件 が実用的です。もっと必要なら、そのユニットがやりすぎているか契約が不明確なことが多いです。

大量のハッピーパステストを生成することの問題点は何ですか?

ハッピーパスのテストは主に「例がまだ動く」ことを確認するだけで、本番で壊れる原因を見逃しがちです。

高シグナルテストは次を狙います:

  • 境界(0/1/最大、空/null、オフバイワン)
  • 障害モード(タイムアウト、無効入力、依存サービスエラー)
  • インバリアント(「エラー時に部分的な書き込みをしない」などの常に成り立つルール)
AIにテストを生成してもらう前に何を書いておくべきですか?

まずは一息で読める小さな契約を書いてください:

  • 入力: 型、許容範囲、空/欠如の定義
  • 出力: 成功時の形とエラーの形
  • 副作用: 何が書き換えられるか(DB、ファイル、ネットワークなど)
  • 「絶対に起きてはならないこと」: クラッシュ、沈黙するデータ損失、重複課金、部分的書き込み

その契約からテストを生成してください。単なる例だけから生成するとハッピーパスばかりになります。

どの境界ケースを優先してテストすべきですか?

まずはこれを優先してテストすべきです:

  • 最小/最大値(0、1、最大、最大+1)
  • 空か存在か(""、[]、null/undefined)
  • オフバイワン(n-1、n、n+1)
  • フォーマットの端(空白のみ、先頭ゼロなど)
  • 時間の境界(有効期限の直前/直後)

入力の各次元につき1〜2件選び、各テストが固有のリスクをカバーするようにします。

浅いテストではなく良い「障害モード」テストを書くにはどうすればいいですか?

良い障害モードテストは2つを証明します:

  1. 関数が明確で期待されるエラーを返すこと(型、メッセージ、ステータス)
  2. 安全に失敗すること:
  • 部分的な状態変更がない
  • 内部の詳細を漏らさない
  • 想定外の再試行や副作用がない

DB書き込みが関与するなら、失敗後にストレージで何が起きたかを必ずチェックしてください。

インバリアントをテストのアサーションにどう変換しますか?

基本的な方法: インバリアントを観測可能な結果に変えてアサーションを書く。

例:

  • 「合計は負にならない」→ expect(total).toBeGreaterThanOrEqual(0)
  • 「エラー時に状態は変わらない」→ 新しい行が追加されていない/フラグが変更されていないことをアサートする
  • 「冪等性」→ 2回呼んでも状態が変わらないことを確認する

返り値と副作用の両方をチェックする方が強固です。多くのバグは「OKが返ったが書き込みが間違っている」ケースで起きます。

ハッピーパステストはいつ残すべきですか?

ハッピーパステストは、インバリアントを守る場合や重要な統合を固定化する場合に価値があります。

残すべき良い理由:

  • 通常入力で重要なインバリアントをアサートする(例: 丸め規則)
  • 呼び出し側が依存するAPI契約を固定する
  • 過去のインシデントの回帰を防ぐ

それ以外は、境界/障害のテストに置き換える方が効果的です。

テストコードを生成する前にモデルに何を出力させるべきですか?

まずはPHASE 1: 計画のみを要求してください。

モデルに次を出力させます:

  • 最大6–10件の提案テスト
  • 各テストについて: 目的、セットアップ、入力、期待結果、なぜ高シグナルなのか
  • 小さな境界マトリクス
  • 障害モードの一覧
  • 3–5件のインバリアントとその検証方法

計画を承認してからPHASE 2でテストコードを生成させると、20件の似たようなテストが出るのを防げます。

モックしすぎて脆くなるテストを避けるには?

モックを最小限に保ち、実際に制御できる境界だけをモックしてください。

オーバーモックを避けるための指針:

  • 実装内部のヘルパーをモックして実装を反映しない
  • 可能ならインメモリの実実装や小さなフェイクを使う
  • クロックや乱数はアサーションに影響する場合のみモックする

リファクタで振る舞いが変わらないのにテストが壊れるなら、それは過度なモックか実装依存になっていることが多いです。

AI生成テストが低価値かどうかを素早く見分けるには?

簡単な削除テストを行ってください:

  • テストを削除しても境界、障害モード、インバリアントのいずれも失われないなら、そのテストは価値がありません。

重複を探す:

  • 2つのテストが同じバグで失敗するなら、より強い方を残す
  • アサーションが「nullでない」や「ステータス200」だけなら強化するか削除する
目次
なぜハッピーパステストの自動生成は時間を無駄にするのか3つのターゲット: 境界、障害モード、インバリアント準備: テストを書く前に小さな契約を抽出するプロンプトパターン: 高シグナルテストの青写真ステップバイステップ: プロンプトを実行して出力をテストに変えるインバリアントをアサーションへ落とし込む方法障害モード: 安全に失敗することを証明するテストを書く低価値テストを生む一般的な罠例: 1つの機能を小さく強いテストセットに変える高シグナルなAI生成テストのためのクイックチェックリスト次のステップ: 再利用可能なワークフローにするよくある質問
共有
Koder.ai
Koderで自分のアプリを作ろう 今すぐ!

Koderの力を理解する最良の方法は、自分で体験することです。

無料で始めるデモを予約