Claude Media
Claudeがテストだけ通すハードコードを防ぐプロンプトの書き方

Claudeがテストだけ通すハードコードを防ぐプロンプトの書き方

Claudeがテストケースの値だけに反応する分岐を書いてしまう問題を、公式ドキュメントの文言でどう防ぐかをまとめます。CLAUDE.mdへの落とし込み方も扱います。

Claudeがテストだけ通すハードコードを書いてしまう理由

Claudeはテストを通すことを優先しすぎると、対象のロジックそのものではなく、個々のテストケースの入力値だけに反応するコードを書くことがあります。公式ドキュメントはこの傾向を「テストを通すことに重点を置き過ぎて、汎用的な解決策を犠牲にすることがある」と明記しています。複雑なリファクタリングでは、標準的なツールを直接使わずヘルパースクリプトで回り道することもあると公式ドキュメントは指摘しています。

具体例で考えると分かりやすくなります。「入力が5のとき10を返す関数を実装して」というテストが1件しかない状態で実装を頼むと、if (x === 5) return 10; のような分岐だけを書いて済ませてしまう余地が生まれます。このコードはテストを通しますが、入力が6のときの挙動は何も保証されません。

テストを複数用意しても根絶にはなりません。「入力が5のとき10、7のとき14を返す」という2件のテストに対して、if (x === 5) return 10; if (x === 7) return 14; のような分岐を積み重ねるだけでも、テストケースの数を増やした分だけ分岐も増やせば両方を通せます。テストの件数を増やす対策は発生率を下げますが、実装側が一般式(x * 2)ではなく個別の対応表を書く余地そのものは残ります。テストの合否は最も明確な成功シグナルであり、そこだけを最短距離で満たした結果と見ることもできます。プロンプト側で「個別の対応ではなく一般式を書く」と明示的に禁止するほうが確実です。

公式が推奨するプロンプトの文言

対処法は、テストの役割そのものを明文化した指示を渡すことです。公式ドキュメントは次の文言をそのまま使える例として挙げています。

Please write a high-quality, general-purpose solution using the standard tools
available. Do not create helper scripts or workarounds to accomplish the task more
efficiently. Implement a solution that works correctly for all valid inputs, not just
the test cases. Do not hard-code values or create solutions that only work for specific
test inputs. Instead, implement the actual logic that solves the problem generally.
 
Focus on understanding the problem requirements and implementing the correct algorithm.
Tests are there to verify correctness, not to define the solution. Provide a principled
implementation that follows best practices and software design principles.
 
If the task is unreasonable or infeasible, or if any of the tests are incorrect, please
inform me rather than working around them. The solution should be robust, maintainable,
and extendable.

ポイントは3つです。1つ目は、標準ツールの使用を求め、ヘルパースクリプトによる回り道を塞ぐことです。2つ目は、「テストは正しさを検証するものであり、解を定義するものではない」とテストの役割を明言することです。3つ目は、テストや要件自体が不合理なときは回避するのではなく報告するよう求めることです。3つ目を入れておくと、テストの前提が壊れているケースまでハードコードで押し切られる事故を防げます。

2つ目のように禁止だけでなく理由まで添える書き方は、テストのハードコードに限らずプロンプト全般で効く技法です。理由を書くと、Claudeはその意図を汎用化して応用しやすくなります。プロンプトの書き方の原則そのものはClaudeプロンプトの書き方 — 良い指示を出す7つのコツにまとめているので、あわせて参照してください。

ヘルパースクリプトによる回り道も合わせて防ぐ

前節の文言だけでも「ヘルパースクリプトを作らない」という指示は含まれています。それでも回り道を完全に塞ぎたい場合は、一時ファイルの扱いを定めた別の公式文言を併用できます。公式ドキュメントは、複雑な作業の途中でPythonスクリプトなどを「一時的な作業場」として作ること自体は成果を高める場合があると認めつつ、新規ファイルの増加を抑えたいなら後片付けを求める文言を挙げています。

If you create any temporary new files, scripts, or helper files for iteration, clean up
these files by removing them at the end of the task.

この文言は「ヘルパースクリプトを作るな」ではなく「作ってもよいが最後に消せ」という指示です。テストだけ通すハードコードを防ぐ文言と役割が違うので、置き換えではなく併用します。実装の探索に一時スクリプトを使うこと自体は妨げず、成果物に回り道の跡だけが残らないようにする、という切り分けです。

CLAUDE.mdか、その場の指示か

この文言は2箇所のどちらかに置けます。1回限りの依頼ならプロンプトにそのまま貼り、繰り返す作業なら短く要約してCLAUDE.mdに置きます。CLAUDE.mdは会話の開始時に毎回読み込まれるファイルで、Claudeがコードから推測できない前提や規約を置く場所です。

# 実装方針
- テストケースの値に対する分岐ではなく、要件を満たす汎用ロジックを書く
- ヘルパースクリプトでの回避をせず、標準ツールを使う
- テストや要件が不合理なら報告し、ハードコードで押し切らない

長いCLAUDE.mdは個々の指示が埋もれて無視されやすくなるので、置く内容は上記のように絞ります。テスト駆動開発の進め方とCLAUDE.mdへの書き方の切り分けはClaude CodeでTDDを回す手順にまとめています。

テストを書かせる指示と組み合わせる

このプロンプトは、実装フェーズにだけ効かせても十分ではありません。Claude自身にテストを書かせる場面では、テストの作りが緩いと、ハードコードでも通ってしまう抜け道が先に生まれます。境界値や異常系を含む複数のテストケースを用意させ、1件だけのテストで実装を任せない運用を組み合わせると、ハードコードで通せる余地そのものが狭まります。

テストを書かせる指示自体にも、件数と種類を条件として添えます。

テストは最低4件用意してください。通常値1件、境界値(0と最大値)2件、
異常系(不正な入力)1件を含めること。特定の入力値に対する分岐で
通せてしまう実装を弾けるだけの多様性を持たせてください。

「境界値」「異常系」という種類を先に指定すると、テストが1〜2件の通常値だけに偏る事態を避けられます。テストの件数と実装内の条件分岐の数が近いほど、後述するハードコードの兆候に当たりやすくなります。

Playwrightでのエンドツーエンドテストのように、画面の見た目まで検証対象になる場面では、特定のシナリオの画面遷移だけを再現するコードが書かれるリスクも同じ構造で起きます。テストの自動実行をhookに組み込む手順はClaude CodeでPlaywrightのE2Eテストをhookで自動実行するにまとめています。しきい値の判定処理のように、境界値の扱いを個別に書き分けやすい場面での対策はClaude Codeでk6の負荷テストスクリプトを作成する手順を参照してください。

似ているが別の問題と混同しない

「テストだけ通すハードコード」と紛れやすい問題が2つあります。区別しておくと、対処するプロンプトを取り違えずに済みます。

問題内容対処するプロンプトの要点
テストのみ通すハードコード内容テストケースの入力値だけに反応する分岐を書く対処するプロンプトの要点本記事の文言(汎用ロジックを要求)
オーバーエンジニアリング内容頼まれていない抽象化・設定可能性・防御的コードを増やす対処するプロンプトの要点依頼された変更だけに留めるよう要求する別文言
ハルシネーション内容開いていないファイルの内容を推測して答える対処するプロンプトの要点ファイルを読むまで推測しないよう要求する別文言

オーバーエンジニアリングは公式ドキュメントがClaude Opus 4.5とClaude Opus 4.6の傾向として明記している問題で、ハードコードとは逆方向の失敗です。頼まれていない抽象化や設定可能性を増やす動きは、テストの入力値だけに反応する動きとは真逆の方向に振れています。片方を防ぐ指示だけでは、もう片方は防げません。両方が気になる場合は、それぞれの文言を別々に渡す必要があります。同じプロンプトの中に両方の指示を含めても構いませんが、指示同士が矛盾しないよう「必要な処理は省略せず書くが、頼まれていない拡張は追加しない」という切り分けを添えておくと読み違いが減ります。

それでも起きたときの見つけ方

プロンプトを渡していても、複雑な実装では紛れ込むことがあります。レビューで確認しやすい箇所は次の3つです。

  • 実装の分岐条件に、テストファイルに出てくる具体的な数値や文字列がそのまま使われていないか
  • テストケースの件数と、実装内の条件分岐の数が近すぎないか(1対1に近いほど疑わしい)
  • テストを1件追加しただけで、実装側の分岐も1つ増える構造になっていないか

これらは目視でも見つかりますが、テストを書いたセッションとは別の文脈で実装させておくと、実装側が自分の書いたテストの意図に引きずられないため、そもそも紛れ込みにくくなります。公式のベストプラクティスも「一方のClaudeにテストを書かせ、別のClaudeにそれを通すコードを書かせる」進め方を挙げています。文脈を分けて実装させる具体的な手順はClaude CodeでTDDを回す手順で扱っています。

疑わしい実装が見つかったら、別の文脈でその1点だけを確認させる方法もあります。

src/calc.ts の実装を確認してください。テストファイルに出てくる
入力値や期待値がそのままハードコードされている箇所がないか、
一般化されたロジックになっているかだけを見てください。

対象を「ハードコードの有無」1点に絞ることで、無関係な指摘まで返ってくる事態を避けられます。

よくある質問

Claude Codeでなく、Claude APIやAgent SDKでも使えますか

使えます。この文言はモデルへの指示として渡す普通の文章で、Claude Code固有の機能に依存していません。APIならシステムプロンプトかユーザープロンプトに、Agent SDKで組んだエージェントなら同じ位置に渡せば、Claude Codeでの使い方と変わりません。渡す場所がCLAUDE.mdか、それに相当する常設のシステムプロンプトかという違いだけです。

テストが用意できない作業でも意味がありますか

「テストのみ通すハードコードを防ぐ」という狙いそのものは、テストが存在しない場に対しては働きません。ただし同じプロンプトに含まれる「標準ツールを使い、一般解を実装する」という部分は、テストの有無に関係なく効きます。テストを用意する時間が取れない小さな修正でも、この部分だけを渡す使い方は成立します。

まとめ

Claudeにテストだけ通すハードコードを書かせないためには、標準ツールの使用とヘルパースクリプトの禁止、テストの役割の明言、不合理な要件への報告義務という3点を含むプロンプトを渡します。1回限りの依頼ならその場に貼り、繰り返す作業ならCLAUDE.mdへ短く要約して置きます。テストの書き方自体を見直す運用と組み合わせると、ハードコードで通せる余地はさらに狭まり、レビューの手間も減らせます。

この記事を共有:XはてブLinkedIn