テストケース生成
Claudeを使って包括的なテストスイートを生成 — ユニットテスト、統合テスト、エッジケース、テストデータ。
学べること
- ハッピーパスだけでなくエッジケースとエラー条件もカバーするユニットテストを生成するClaudeへのプロンプト方法
- 統合テスト、テストデータフィクスチャ、プロパティベースのテストケースを生成するテクニック
- Claudeを使って既存のテストスイートのカバレッジのギャップを監査する方法
ユースケース
テストを書くことはソフトウェア開発において最も高い価値を持ちながら最も時間がかかる部分の一つです。ほとんどの開発者はより多くのテストを書くべきだと知っています——ボトルネックは意図ではなく時間です。あらゆるエッジケースを考え、テストハーネスを書き、現実的なテストデータを生成し、コードが変わるにつれてテストを維持するすべてに大きな努力が必要です。Claudeはこの作業を劇的に加速できます。
重要な洞察は、テスト生成はClaudeが特に得意とすることです。なぜならケースの体系的な列挙を必要とするからです——これはフロー状態にある人間よりClaudeが得意です。明白な入力についてテストを書いて完了と言いたくなるところを、Claudeは体系的に考えます:入力が空の場合は?制約の境界にある場合は?依存関係が予期しない型を返す場合は?2つの有効な入力が驚くような方法で相互作用する場合は?
これはテストタイプ全体に適用されます。ユニットテストでは、Claudeは単一の関数に焦点を当てた断言を書きます。統合テストでは、ClaudeはAPIに対する完全なリクエスト/レスポンスサイクルを生成できます。テストデータでは、Claudeはエンティティ間の適切な関係を持つ現実的なフィクスチャを作成します。プロパティベースのテストでは、Claudeはコードが常に満たすべき不変量を説明できます。
ステップバイステップガイド
ステップ1:テスト対象のコードとテストフレームワークを提供する
常に以下を指定することから始めましょう:
- 使用しているテストライブラリ/フレームワーク(Jest、pytest、Goのtesting、JUnit、RSpecなど)
- 任意のモッキングライブラリ(Jestのモック、unittest.mock、sinonなど)
- テストしたいコード(完全な関数またはクラスを貼り付ける)
Claudeはフレームワークを知って構文的に正しいテストを生成し、正しいアサーションAPIを使う必要があります。
ステップ2:カテゴリ全体の体系的なカバレッジを依頼する
「いくつかのテスト」を依頼するだけでなく、特定のカテゴリをカバーするようClaudeに依頼しましょう:
- ハッピーパス — 正しい期待されるアウトプットを持つ標準的な有効な入力
- 境界条件 — 有効範囲のエッジの値(0、-1、最大int、空文字列、単一要素など)
- 無効な入力 — null/undefined、間違った型、範囲外の値
- エラー条件 — 依存関係が失敗したとき、ネットワークが利用できないときなど
- 並行性またはタイミング — 適用可能な場合
プロンプトを構造化しましょう:「次をカバーするユニットテストを書いてください:(1) 通常の使用、(2) 境界値、(3) エラーを投げるべき無効な入力、(4) 外部依存関係がエラーを返す場合。」
ステップ3:現実的なテストデータを依頼する
プレースホルダーのテストデータ(name: "test"、id: 1)は実際の失敗を見つけられない脆弱なテストを生成します。現実的に見えるデータをClaudeに依頼しましょう:
「現実的に見えるテストデータを使ってください——実際に見える名前、有効なメール形式、現実的なドル金額、実際のISO日付文字列。」
関係を持つ複雑なエンティティグラフのためには、関係を説明してすべての外部キー制約とビジネスルールを満たすフィクスチャデータを生成するようClaudeに依頼しましょう。
ステップ4:意図を文書化するテストの説明を依頼する
良いテスト名と説明はドキュメントです。テストされている関数だけでなく、シナリオと期待される結果を説明するテスト名を書くようClaudeに依頼しましょう:
- 弱い:
test_process_payment() - 強い:
test_process_payment_raises_InsufficientFunds_when_balance_is_below_amount()
プロンプトに追加しましょう:「各テストをテストされているシナリオと期待される結果を説明するように命名してください。パターンに従ってください:test_[function]_[scenario]_[expected]。」
ステップ5:既存のテストのギャップを監査する
既存のテストファイルとテストするコードを貼り付けて、依頼しましょう:
「これらの既存のテストをコードと照合してレビューしてください。現在カバーされていないケースは何ですか?欠けているテストシナリオをリストし、欠けているテストを書いてください。」
これはテストのためのClaudeの最も効率的な使い方の一つです——本番コードとテストコードの両方を読み、デルタを特定します。
プロンプトテンプレート
フレームワーク:[pytest / Jest / Goのtesting / JUnit / など]
モッキングライブラリ:[unittest.mock / jest.fn() / sinon / など — または「不要」]
テストしたい関数/クラスはこちらです:
[テスト対象のコードを貼り付けてください]
以下をカバーする包括的なテストを書いてください:
1. 典型的な有効な入力による通常の使用(ハッピーパス)
2. 境界条件(空の入力、単一アイテム、最大値、最小値)
3. エラーまたはエラー状態を発生させるべき無効な入力
4. [任意のドメイン固有のケース、例:「データベースコールが失敗する場合」]
5. [適用可能な場合の任意の並行性または非同期動作]
要件:
- 「test」や「1234」などのプレースホルダーではなく現実的なテストデータを使う
- シナリオと期待される結果を説明するように各テストを命名する
- 何がテストされているかを説明する簡単なコメントを各テストグループの上に追加する
- 任意の外部依存関係をモックする([それらをリスト、例:「データベースコール」、「HTTPリクエスト」])
ヒントとベストプラクティス
-
関数ごとではなく動作ごとに一つのテスト — 大きな関数ごとの一つのテストではなく、異なる動作ごとに一つのテストを書くようClaudeに依頼しましょう。*「各テストは正確に一つのことを検証すべきです。テストに複数の論理アサーショングループがある場合は分割してください。」*これによりテストの失敗が正確な問題を特定できます。
-
ポジティブとネガティブの両方の断言を依頼する — 多くのテストスイートは物事が正しく動作することを検証するだけです。無効な状態のテストも書くようClaudeに依頼しましょう:「無効な入力が与えられた場合に(任意の例外ではなく)正しい例外タイプを発生させることを検証するテストを含めてください。」
-
プロパティベースのテストの説明を生成する — 数学的なプロパティ(可換性、冪等性、単調性)を持つ関数については、Claudeに不変量を説明するよう依頼しましょう:「この関数について、入力に関係なく常に保持されるべきプロパティは何ですか?それらを説明し、フレームワークがサポートしている場合はプロパティベースのテストを書いてください(PythonのHypothesis、JavaScriptのfast-checkなど)。」
-
ハードコードされたフィクスチャではなくテストデータファクトリーを依頼する — エンティティが重いテストのために、ハードコードされたオブジェクトではなくファクトリー関数を生成するようClaudeに依頼しましょう。「ハードコードされたテストオブジェクトの代わりに、合理的なデフォルトとキーワードオーバーライドを持つ
make_order()ファクトリー関数を書いてください。各テストはそれに関連するフィールドのみをカスタマイズできます。」 -
テストを書く前にClaudeにテスト計画を作成させる — 複雑なコードについては、まずテスト計画を依頼しましょう:*「コードを書く前に、テストするすべてのシナリオとその理由をリストしてください。計画を確認してから、テストを書いてください。」*これにより、特定のテスト実装にコミットする前にカバレッジ戦略の決定が表面化します。
試してみよう
コードベースから純粋な関数——副作用なし、外部依存関係なし、ただ入力と出力の関数——を選びましょう。Claudeに以下のプロンプトで貼り付けましょう:
「この関数の包括的なpytestテストを書いてください。カバーすること:少なくとも3つの異なる有効な入力による通常の使用、境界条件(空、None、単一要素のリスト、非常に大きな値——関連するものなら何でも)、および例外を発生させるべき少なくとも3つの無効な入力ケース。現実的なテストデータを使いシナリオを説明するように各テストを命名してください。」
生成されたテストを実行してください。Claudeが自分では書かなかったエッジケースをどれだけカバーしたかを確認しましょう。