Skip to content
プロダクト

ケーススタディ:Coding Agentによる自動テスト生成

Coding Agentを使用してテストされていないモジュールの単体テストを自動生成し、95%以上のカバレッジを達成するワークフローの実践的なウォークスルーです。

JT
JieGou Team
· · 2 分で読めます

テストカバレッジは、誰もが重要だと同意しながら、改善の責任を負いたがらないメトリックの1つです。おなじみのパターンです:コードベースは90%のカバレッジで始まり、テストなしでいくつかの機能が出荷され、「後で戻ります」とリファクタリングがテスト更新をスキップします。6ヶ月後には60%になり、回復するのは誰もサインアップしていないフルタイムの仕事のように感じられます。

このケーススタディでは、あるチームがCoding Agent付きのJieGouワークフローを使用して、3週間で60%から94%のテストカバレッジに到達した方法を解説します — 最小限の人的介入で自動的に。

問題

対象のコードベースは312モジュールのNode.jsバックエンドでした。カバレッジは数ヶ月間着実に低下していました:

  • 全体テストカバレッジ60%、年初の85%から低下
  • テストがゼロの47モジュール — 主にユーティリティ関数、データトランスフォーマー、バリデーションロジック
  • テストなしで新機能が出荷されている。開発者が納期に集中しているため
  • CIパイプラインはテストを実行するがカバレッジしきい値を強制していないため、誰かが確認するまで低下は見えなかった

チームは「テスト記述スプリント」を2回割り当てようとしました。両方とも顧客エスカレーションが発生した際に優先度が下げられました。手動テスト記述は遅く、退屈で、他のすべての優先事項と競合します。

ワークフロー

チームはJieGouで4ステップのワークフローを構築し、コードがmainにマージされるたびに自動的にトリガーされます。生成されたテストの修正が必要でない限り、手動介入は不要です。

ステップ1:トリガー — PRマージ時のGitHub Webhook

ワークフローは、プルリクエストがmainにマージされた時に発火するWebhookトリガーで開始します。

trigger:
  type: webhook
  source: github
  events: ["pull_request.closed"]
  filters:
    - field: "action"
      value: "closed"
    - field: "pull_request.merged"
      value: true
    - field: "pull_request.base.ref"
      value: "main"

Webhookペイロードには変更されたファイルのリスト、マージコミットSHA、PRメタデータが含まれます。これらすべてが次のステップに供給されます。

ステップ2:分析 — テストされていない関数の特定

レシピステップがWebhookからの変更ファイルリストを取得し、最新のカバレッジレポートと照合します。レシピプロンプトは簡潔です:

step: analyze-coverage
type: recipe
model: claude-sonnet-4-6
input:
  changed_files: "{{trigger.pull_request.changed_files}}"
  coverage_report: "{{secrets.COVERAGE_REPORT_URL}}"
prompt: |
  You are a test coverage analyst. Given the list of changed files
  and the coverage report (lcov format), identify:

  1. Which changed files have less than 80% line coverage
  2. Which exported functions in those files have zero coverage
  3. The function signatures and a brief description of what each does

  Output a JSON array of objects with fields:
  file_path, function_name, signature, description, current_coverage

このステップはテストが必要な関数の構造化リストを正確に生成します。既に適切なカバレッジのあるファイルをフィルタリングするため、Coding Agentは既にテストされたコードに時間を無駄にしません。

ステップ3:生成 — Coding Agentがテストを記述

ここでCoding Agentが重い作業を行います。テストされていない関数のリストを受け取り、リポジトリをクローンし、各関数の単体テストを記述します。

step: generate-tests
type: coding-agent
model: claude-sonnet-4-6
repo: "{{secrets.REPO_URL}}"
branch: "test-gen/{{trigger.pull_request.number}}"
maxTurns: 30
sandbox:
  memory: "1GB"
  timeout: "5m"
  network: false
tools:
  - read
  - write
  - edit
  - bash
  - glob
  - grep
input:
  untested_functions: "{{steps.analyze-coverage.output}}"
task: |
  You are a senior test engineer. Your job is to write unit tests for
  the following untested functions:

  {{untested_functions}}

  Instructions:
  1. Read the source file for each function to understand its behavior
  2. Read existing test files in the same directory for style conventions
  3. Write tests using the project's test framework (vitest)
  4. Each test file should cover: happy path, edge cases, error handling
  5. Run `npm test -- --reporter=verbose <test-file>` after writing each
     test file to verify all tests pass
  6. If a test fails, read the error, fix the test, and re-run
  7. Do NOT modify source code — only create or update test files

  Match the existing test style: describe blocks, clear test names,
  arrange-act-assert pattern. Use the existing fixtures and helpers
  where available.

ここでの重要な設定選択:

  • モデル:Claude Sonnet 4.6 — 大量テスト生成に十分な速度、複雑な関数シグネチャとエッジケースを理解するのに十分なインテリジェンス。
  • サンドボックス:1 GBメモリ、5分タイムアウトnpm test実行に十分な余裕があり、暴走プロセスのリスクなし。
  • ネットワーク無効 — エージェントは外部アクセス不要;すべてクローンされたリポジトリ内。
  • maxTurns: 30 — 複数のテストファイルに対して反復し、複数のサイクルにわたって障害を修正可能。

タスク説明には重要な指示が含まれています:まず既存のテストファイルを読むこと。これにより、生成されたテストがチームの規約に一致します — 同じアサーションスタイル、同じdescribe/it構造、同じフィクスチャパターン。これなしでは、生成されたテストは技術的に正しくてもスタイル的に一貫性がなく、レビュー時に摩擦が生じます。

ステップ4:提出 — 結果でPRを作成

Coding Agentの作業完了後、最終レシピステップが生成されたテストでプルリクエストを作成し、テスト結果をPR説明に含めます。

step: submit-pr
type: recipe
model: claude-sonnet-4-6
input:
  modified_files: "{{steps.generate-tests.modified_files}}"
  test_output: "{{steps.generate-tests.output}}"
  source_pr: "{{trigger.pull_request.number}}"
prompt: |
  Create a pull request with the following:
  - Title: "test: auto-generated tests for PR #{{source_pr}}"
  - Body: Include a summary of tests added, functions covered,
    and the full test output showing all tests passing
  - Label: "auto-tests"
  - Request review from the original PR author

PRにはauto-testsラベルが付けられるため、チームは生成されたテストPRをフィルタリングしてバッチレビューできます。元のPR作者にレビューをリクエストすることで、コードに最も精通した人が最初にテストを確認します。

結果

チームはこのワークフローを3週間、mainへの各マージで実行しました。数字は以下の通りです:

メトリック
開始カバレッジ60%
終了カバレッジ94%
生成されたテスト847
作成されたプルリクエスト42
平均PRレビュー時間12分
既存バグを発見したテスト23
1日あたりの平均コスト約$4.50(Claude API)

いくつかの点が目立ちます。

42PR中847テストは、PR当たり約20テストを意味します。ほとんどのPRは2-4のソースファイルをカバーし、関数あたり5-6テスト(ハッピーパス、境界条件、エラーケース、null/undefined入力、型強制エッジケース)。

平均12分のレビュー時間は注目に値します。ほとんどの生成テストは最初のパスで正しかったです。主なレビューコメントはスタイル的なもの — テスト説明の名前変更、フィクスチャデータをより現実的に調整。機能的な修正が必要なテストはほとんどありませんでした。

23テストが実際のバグを発見しました。これが最も興味深い結果です。Coding AgentがISO 8601形式を期待する日付解析関数のテストを書き、タイムゾーンオフセット付きタイムスタンプで関数がサイレントにInvalid Dateを返すことを明らかにしました。そのバグは4ヶ月間本番にありました。バリデーションロジック、ページネーションヘルパーのオフバイワンエラー、キャッシングモジュールの競合状態でも同様の発見がありました。

1日$4.50のClaude APIコストは、節約されたエンジニアリング時間と比較して些細なものです。控えめな見積もり:テスト1つあたり15分で847テストを手動で書くと約212時間 — フルタイムエンジニアの5週間以上の時間がかかります。

学んだ教訓

このワークフローを3週間実行した後、チームは何がうまくいき、何がうまくいかなかったかに基づいてアプローチを改良しました。

純粋関数から始める

ワークフローの最初のバージョンはすべてのテストされていないコードを対象としていました。これは純粋関数 — ユーティリティ、バリデーター、トランスフォーマー、フォーマッター — ではうまく機能しました。明確な入力、明確な出力があり、副作用がないためです。エージェントは関数を読み、契約を理解し、包括的なテストを書くことができました。

データベース接続、外部API呼び出し、共有ミュータブル状態を持つ複雑なモジュールはより困難でした。エージェントは時に過度にモックしたり、動作ではなく実装の詳細をテストしたりするテストを生成しました。チームは分析ステップを調整して、まず純粋関数を優先し、複雑なモジュールを手動レビューのためにキューイングしました。

既存のテスト例を提供する

最も影響のある変更は、タスク説明に「同じディレクトリの既存テストファイルを読んでスタイル規約を確認する」という指示を追加したことです。この指示前は、エージェントは機能的に正しいが、テストスイートの他の部分とは異なるアサーションパターン、異なるdescribeブロック構造、異なる命名規約のテストを生成していました。指示後は、生成されたテストは手書きのものとほぼ区別がつかなくなりました。

PR作成前にテストを実行する

ワークフローの初期の反復では、検証されていないテストのPRを提出していました。インポートエラー、欠落したフィクスチャ、アサーション失敗があるものもありました。Coding Agentタスク内にnpm testステップを追加し — 完了前に失敗を修正するよう指示する — ことで、これらの問題のほぼすべてを排除しました。エージェントの反復ループ(テストを書く、テストを実行、エラーを読む、テストを修正、再実行)は人間の作業方法とまったく同じですが、より高速です。

カバレッジだけでなく品質のレビュー

カバレッジは代理メトリックです。expect(result).toBeDefined()をアサートするテストは技術的に関数をカバーしますが、動作を検証しません。チームは生成されたテストPR用のレビューチェックリストを追加しました:

  • 各テストは関数が実行されるだけでなく、意味のある動作を検証していますか?
  • エッジケースがカバーされていますか(null入力、空配列、境界値)?
  • テスト説明はどの動作がテストされているかを明確に述べていますか?
  • アサーションは具体的ですか(.toBeTruthy()ではなく.toBe(42))?

ほとんどの生成テストはこのチェックリストを変更なしでパスしました。そうでなかった少数は12分のレビュー中に簡単に見つけて修正できました。

完全な設定

このワークフローを再現したいチーム向けに、完全なステップ設定を示します:

workflow:
  name: "Auto Test Generation"
  description: "Generate unit tests for untested code on PR merge"

  trigger:
    type: webhook
    source: github
    events: ["pull_request.closed"]
    filters:
      - field: "pull_request.merged"
        value: true
      - field: "pull_request.base.ref"
        value: "main"

  steps:
    - id: analyze-coverage
      type: recipe
      model: claude-sonnet-4-6
      # ... (上記ステップ2参照)

    - id: generate-tests
      type: coding-agent
      model: claude-sonnet-4-6
      dependsOn: [analyze-coverage]
      # ... (上記ステップ3参照)

    - id: submit-pr
      type: recipe
      model: claude-sonnet-4-6
      dependsOn: [generate-tests]
      # ... (上記ステップ4参照)

ワークフローはテストされていない関数の数に応じて8-15分でエンドツーエンドで実行されます。そのほとんどの時間はCoding Agentがテストファイルを反復し、各テスト後にnpm testを実行することに費やされます。

次のステップ

チームは現在、ワークフローを2つの方向に拡張しています:

  1. 統合テスト — 既存のテストヘルパーとデータベースフィクスチャを使用して、APIエンドポイントの統合テストを生成する別のCoding Agentステップ
  2. カバレッジ強制 — ベースラインが強制するのに十分高くなったため、カバレッジが90%を下回るとビルドを失敗させるCIチェック

より広い教訓:テストカバレッジは手動の雑用である必要はありません。適切なワークフローがあれば、既存のCI/CDと並行して実行される自動パイプラインとして扱えます — 専用スプリントなし、優先度低下なし、カバレッジ負債なし。

Coding AgentはProプラン以上で利用可能です。最初のコーディングワークフローを構築する

coding-agent case-study test-generation automation ci-cd
この記事をシェアする

この記事はお役に立ちましたか?

ワークフローのヒント、製品アップデート、自動化ガイドをメールでお届けします。

No spam. Unsubscribe anytime.