Part 5: AI × 開発 実践
Chapter 29: AI を使ったテスト作成
テストケースの自動生成とカバレッジ改善
テストを書くことは品質の担保に不可欠ですが、時間がかかる作業でもあります。AI を使えば、テストケースの生成・エッジケースの洗い出し・カバレッジの改善を大幅に効率化できます。この章では AI と一緒にテストを書くための実践的な手法を学びます。
29.1 テストの種類
AI に適切なテストを生成させるには、まずどの種類のテストを書くか明示する必要があります。
| テストの種類 | 対象 | 特徴 | 主なツール |
|---|---|---|---|
| 単体テスト (Unit Test) | 関数・クラス単体 | 高速、依存を Mock する | Jest, Vitest |
| 結合テスト (Integration Test) | モジュール間の連携 | DB や API と実際に繋ぐ | Supertest, Playwright |
| E2E テスト (End-to-End) | ユーザーの操作フロー | ブラウザを実際に操作する | Playwright, Cypress |
プロンプトでテスト種別を明示する
以下の関数の**単体テスト**を書いてほしい。
DB は Mock し、関数の純粋なロジックだけをテストすること。
テストフレームワークは Jest を使う。
[関数のコードを貼り付ける]29.2 テストケースの自動生成
実装コードからテストを生成する
既存の実装コードを渡すだけで、AI がテストケースを生成します。
プロンプト例:
以下の TypeScript 関数のテストを書いてほしい。
【要件】
- 正常系のケースを最低3つ
- 異常系のケース(エラーが投げられるケース)も含める
- テストケース名は日本語でわかりやすく書く
- Jest + TypeScript で書く
【対象コード】
// src/utils/validator.ts
export function validateEmail(email: string): boolean {
if (!email) throw new Error('Email is required');
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
}
export function validatePassword(password: string): { valid: boolean; errors: string[] } {
const errors: string[] = [];
if (password.length < 8) errors.push('8文字以上必要です');
if (!/[A-Z]/.test(password)) errors.push('大文字が1文字以上必要です');
if (!/[0-9]/.test(password)) errors.push('数字が1文字以上必要です');
return { valid: errors.length === 0, errors };
}API エンドポイントのテスト生成
以下の Express エンドポイントの**結合テスト**を書いてほしい。
Supertest を使って HTTP リクエストを実際に送ってテストする。
DB は実際のテスト用 PostgreSQL に繋ぐこと(モックしない)。
【エンドポイント】
POST /api/users/register
- email, password を受け取る
- 重複メールは 409 を返す
- バリデーションエラーは 422 を返す
- 成功時は 201 と user オブジェクトを返す
[コントローラーのコードを貼り付ける]29.3 エッジケースの網羅
AI はエッジケースの洗い出しが得意です。自分では思いつかなかったケースを提案してもらいましょう。
エッジケース洗い出しプロンプト
以下の関数のエッジケースを洗い出してほしい。
考えられるすべての境界値・異常入力・特殊なケースをリストアップしてほしい。
コードは書かなくていい。まずケースの一覧だけ教えてほしい。
// 商品の在庫から注文数を差し引く関数
function deductStock(productId: string, quantity: number): Promise<void>AIが提案するエッジケースの例:
以下のエッジケースが考えられます:
1. 正常系
- 在庫が十分にある場合
- 在庫数 = 注文数のちょうど場合
2. 在庫不足
- 在庫が0の場合
- 在庫数 < 注文数の場合
3. 引数の異常
- quantity が 0 の場合
- quantity が負の値の場合
- quantity が小数の場合
- quantity が整数の最大値を超える場合
- productId が空文字の場合
- productId が存在しない場合
- productId の型が string でない場合 (null, undefined)
4. 並行実行
- 同じ商品に同時に注文が来た場合 (競合状態)
5. DB 関連
- DB 接続が切れている場合
- DB トランザクション中のタイムアウトエッジケースの一覧を確認してから、テストを書いてもらいます。
上のエッジケース一覧のうち、3番目の「引数の異常」と「並行実行」のテストを書いてほしい。境界値分析をさせる
以下の関数の入力値について境界値分析をしてほしい。
どの値でテストすべきか、具体的な数値を教えてほしい。
function calculateShippingFee(totalAmount: number): number {
if (totalAmount >= 5000) return 0; // 5000円以上は送料無料
if (totalAmount >= 2000) return 400; // 2000円以上は400円
return 600; // 2000円未満は600円
}29.4 テストカバレッジの改善
カバレッジレポートを AI に渡す
以下のカバレッジレポートを見て、テストが不足している箇所を特定してほしい。
優先度の高い順にテストを追加する提案をしてほしい。
--- カバレッジレポート ---
File | % Stmts | % Branch | % Funcs | % Lines |
------------------------|---------|----------|---------|---------|
src/services/order.ts | 78.26 | 55.00 | 83.33 | 78.26 |
src/utils/pricing.ts | 92.31 | 80.00 | 100.00 | 92.31 |
src/middleware/auth.ts | 45.83 | 33.33 | 50.00 | 45.83 |
---カバレッジが低い箇所のテスト生成
src/middleware/auth.ts のカバレッジが低い。
このファイルのコードを見て、テストされていない分岐を特定し、
その分岐をカバーするテストを書いてほしい。
[ファイルの内容を貼り付ける]29.5 TDD ワークフロー with AI
TDD と AI を組み合わせた実践的なワークフローです。
TDD × AI のサイクル
実践例: ショッピングカート機能の TDD
Step 1: 要件をまとめてテストケース一覧を出させる
ショッピングカート機能のテストケース一覧を作ってほしい。
【要件】
- 商品をカートに追加できる
- 同じ商品を追加すると数量が増える
- 商品をカートから削除できる
- 数量を変更できる (1以上でないとエラー)
- カートの合計金額を計算できる
- カートを空にできる
テストケースを正常系/異常系に分けてリストアップしてほしい。コードはまだ書かなくていい。Step 2: テストコードを書かせる
上のテストケース一覧を元に、Jest + TypeScript でテストコードを書いてほしい。
Cart クラスはまだ存在しないので、import だけしてテストを書く (Red フェーズ)。Step 3: テストを確認して実装を書かせる
npm test # テストが失敗することを確認上のテストをすべて通すように Cart クラスを実装してほしい。
実装は src/models/cart.ts に書く。Step 4: テストが通ることを確認
npm test # テストが通ることを確認Step 5: リファクタリング
Cart クラスの実装をリファクタリングしてほしい。
以下の観点で改善できる点があれば提案してほしい:
- 可読性
- パフォーマンス
- 型の安全性
テストは変更しないこと。モックの活用
外部依存がある場合、AI にモックを生成させると効率的です。
以下のサービスのテストを書いてほしい。
外部の支払い API (PaymentGateway) と DB (OrderRepository) はモックすること。
Jest の jest.fn() と jest.spyOn() を使ってモックを設定する。
[コードを貼り付ける]AI テスト生成の注意点
テストが「通る」だけでは不十分なケース:
AI が生成したテストコードに以下の問題がないか確認してほしい:
[テストコードを貼り付ける]
特に以下を確認してほしい:
1. テストが実際に意味のある検証をしているか (assertion が十分か)
2. テストが互いに独立しているか (テスト間で状態が共有されていないか)
3. テストの前提条件 (arrange) が正しいか
4. モックが実際の動作を正しく模倣しているかAI が生成したテストをそのまま使うのではなく、内容を理解した上で採用するのが重要です。
まとめ
AI を使ったテスト作成のポイントをまとめます。
| アプローチ | プロンプトのコツ |
|---|---|
| テスト自動生成 | テスト種別・フレームワークを明示する |
| エッジケース洗い出し | まず一覧だけ出させ、コードは後で書かせる |
| カバレッジ改善 | カバレッジレポートを渡して分析させる |
| TDD サイクル | Red → Green → Refactor を明示的に指示する |
| モック生成 | 依存するものを明示し、Mock 方針を伝える |
AI と一緒に TDD を実践することで、テストを書く負担を減らしながら品質を高めることができます。