生成AI研修
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 を実践することで、テストを書く負担を減らしながら品質を高めることができます。

On this page