Claude Codeでテストを自動生成する — Jest/Vitest/pytestの実践パターン集【2026年版】
Claude Codeを使ってテストコードを自動生成する方法を解説。Jest・Vitest・pytestのコマンド例、TDDワークフロー、カバレッジ改善のコツ、よくある失敗パターンまで。日常の開発でそのまま使える実践レシピ集。
エンジニアのゆとです。
テストって、書かなきゃいけないのはわかってるんだけど、後回しになりがちな作業の筆頭だと思う。
機能の実装が終わった後に「さあテスト書こう」ってなると、もうすでに集中力の大半が別のところに飛んでいる。結果、テストなしのままPRを出すか、形式的なテストを最小限だけ書くか——どっちかになりがち。
Claude Codeを本格的に使い始めてから、このテスト周りの状況が変わった。正確に言うと、「テストを書く」という作業そのものは変わっていないんだけど、「自分で0から書く」か「Claude Codeと一緒に書く」かで、スピードが3〜4倍くらい変わる。
この記事では、実際に使っているJest・Vitest・pytestそれぞれでのテスト生成パターンと、TDDワークフローとの組み合わせ、カバレッジ改善のアプローチを具体的なコマンド例付きでまとめる。
なぜClaude Codeはテスト生成が得意なのか
「AIにテストを書かせると、ハッピーパスしか書いてくれない」という印象を持っている人は多いと思う。
その印象は、ChatGPTのようなチャット型AIの話なら当たっている。コードをペーストして「テスト書いて」と頼むと、正常系だけ書いてくれて、エッジケースはほぼスルーされる。
Claude Codeが違うのは、ファイルシステムを直接読めること。「テストを書いて」と頼む前に、実際のソースコードを読んで、型を確認して、依存関係を追って、既存のテストがあればそのパターンを参照する——これを全部やった上でテストを生成できる。
コンテキストの豊かさが出力の質に直結している。
パターン1: 既存コードからテストを生成する(Jest/Vitest)
最も使うケースは「実装済みの関数に対してテストがない」状況。
claude "src/utils/price-calculator.ts のテストを書いて。
テストファイルは tests/utils/price-calculator.test.ts に作成。
Vitestを使用。正常系・異常系・エッジケースを網羅して"
このコマンドだけで、Claude Codeは以下を順番にやってくれる:
price-calculator.tsを読んで関数シグネチャと型を確認tests/以下の既存テストを参照してパターンを統一vitest.config.tsを確認してパスエイリアスなどを把握- 正常系・異常系・境界値のテストケースを生成
実際に出てくるテストはこんな感じになる:
import { describe, it, expect } from 'vitest'
import { calculatePrice } from '../../src/utils/price-calculator'
describe('calculatePrice', () => {
describe('正常系', () => {
it('基本価格を正しく計算する', () => {
expect(calculatePrice({ basePrice: 1000, quantity: 3 })).toBe(3000)
})
it('割引率が適用される', () => {
expect(calculatePrice({ basePrice: 1000, quantity: 10, discountRate: 0.1 })).toBe(9000)
})
})
describe('異常系', () => {
it('数量が0以下の場合はエラーを投げる', () => {
expect(() => calculatePrice({ basePrice: 1000, quantity: 0 })).toThrow('quantity must be positive')
})
it('basePrice が負の場合はエラーを投げる', () => {
expect(() => calculatePrice({ basePrice: -100, quantity: 1 })).toThrow()
})
})
describe('境界値', () => {
it('数量1は正常に処理される', () => {
expect(calculatePrice({ basePrice: 500, quantity: 1 })).toBe(500)
})
it('割引率1.0(100%引き)は0を返す', () => {
expect(calculatePrice({ basePrice: 1000, quantity: 1, discountRate: 1.0 })).toBe(0)
})
})
})
チャット型AIに頼んだときとの違いは、「異常系」「境界値」がちゃんと出てくること。これはソースコードを実際に読んでいるから。
パターン2: カバレッジレポートを渡して穴を埋める
実装が進んでいるがテストカバレッジが低い、というチームあるある状況。
# まずカバレッジレポートを生成
npm run test:coverage
# Claude Code に渡す
claude "coverage/lcov-report/index.html のカバレッジレポートを確認して、
カバレッジが低いファイルを特定して、
未テストの関数・ブランチを優先的にカバーするテストを追加して"
Claude CodeはHTMLファイルも読める。カバレッジレポートを解析して「このファイルのこの関数が0%カバレッジ」という特定まで自動でやってくれる。
lcov-reportのHTMLを直接読ませるのが一番情報量が多いが、coverage/coverage-summary.json でも動く:
claude "coverage/coverage-summary.json を見て、
ステートメントカバレッジが50%未満のファイルをリストして、
それぞれに対してテストを追加する計画を立てて、
まず最も重要なファイルから実装して"
「計画を立ててから実装」という言葉を入れると、Claude Codeが一気にテストを書き始める前に、方針を確認できる。
パターン3: TDDワークフローとの組み合わせ
Claude Codeとの開発で最も生産性が上がるパターンがTDD。
テストを先に書いて、そのテストを通す実装を作らせる。「テストが通ること」という明確なゴールがあると、AIの出力精度が段違いに上がる。
claude "以下の仕様でテストを先に書いて:
機能: ユーザー認証バリデーション
- ユーザー名は3文字以上20文字以下
- メールアドレスの形式バリデーション(RFC準拠)
- パスワードは大文字・小文字・数字をそれぞれ1文字以上含む8文字以上
テストファイル: tests/auth/validation.test.ts
フレームワーク: Vitest
テストを書いたら、次にそのテストが全て通る実装を src/auth/validation.ts に書いて"
このフローの良いところは、「仕様の曖昧さ」がテストを書く段階で可視化されること。
「メールアドレスのRFC準拠」と言っても、user+tag@example.co.jp を許可するか、日本語ドメインを許可するか——Claude Codeがテストを書く過程でこういうエッジケースを考慮したコードを出してくれることがある。見落としていた仕様の穴に気づくきっかけになる。
パターン4: pytest(Python)の場合
Pythonプロジェクトでも基本的な考え方は同じ。
claude "src/services/invoice_generator.py のテストを書いて。
ファイルは tests/services/test_invoice_generator.py に作成。
pytest + pytest-mockを使用。
外部API呼び出し部分はモックして"
モックの処理まで指示しておくのがポイント。言わないと、実際のAPIを叩くテストを書いてくることがある。
# 出力例
import pytest
from unittest.mock import patch, MagicMock
from src.services.invoice_generator import InvoiceGenerator
class TestInvoiceGenerator:
def test_generate_invoice_success(self, mock_payment_api):
generator = InvoiceGenerator()
invoice = generator.generate(
customer_id="cust_001",
amount=50000,
items=[{"name": "コンサルティング費", "price": 50000}]
)
assert invoice.total == 50000
assert invoice.customer_id == "cust_001"
assert invoice.status == "draft"
def test_generate_invoice_with_tax(self, mock_payment_api):
generator = InvoiceGenerator()
invoice = generator.generate(
customer_id="cust_001",
amount=100000,
tax_rate=0.10
)
assert invoice.total == 110000
@patch('src.services.invoice_generator.payment_api')
def test_payment_api_failure_raises_error(self, mock_api):
mock_api.charge.side_effect = Exception("API timeout")
generator = InvoiceGenerator()
with pytest.raises(Exception, match="API timeout"):
generator.generate(customer_id="cust_001", amount=1000)
フィクスチャの自動生成も頼める:
claude "tests/conftest.py に invoice_generator のフィクスチャを追加して。
テスト間で共有するモックオブジェクトとテストデータを含めて"
よくある失敗パターンと対処法
実際に使っていて詰まったパターンをいくつか。
1. モジュール解決エラーが出る
生成されたテストを実行すると Cannot find module が出るケース。
claude "生成したテストを実行したら以下のエラーが出た:
[エラーメッセージをペースト]
tsconfig.json のパスエイリアスを確認して、
vitest.config.ts に必要な設定を追加して"
tsconfig のパスエイリアスをVitestに伝えていないことが原因のことが多い。Claude Codeに両方のファイルを確認させて修正してもらうのが早い。
2. 非同期テストが壊れる
claude "tests/api/user.test.ts の非同期テストが不安定で、
タイミングによってパスしたり落ちたりする。
原因を特定して、適切な await / waitFor の処理に修正して"
テストファイルを直接読ませると、非同期の待機処理が漏れている箇所を特定してくれる。
3. スナップショットテストが毎回変わる
日時やランダムIDが含まれるコンポーネントのスナップショットテストは特にやっかい。
claude "src/components/InvoiceCard.tsx のスナップショットテストが、
日時フィールドのせいで毎回失敗する。
jest.spyOn で Date をモックするか、スナップショットから日時フィールドを除外する方法に直して"
Hooksと組み合わせた継続的テスト監視
せっかくなので、Claude Code Hooksと組み合わせる方法も紹介しておく。
ファイルを編集するたびに「関連テストが通っているか」を自動チェックする設定:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "bash -c 'CHANGED_FILE=\"${TOOL_INPUT_FILE_PATH}\"; TEST_FILE=$(echo $CHANGED_FILE | sed \"s/src\\//tests\\//; s/\\.ts$/.test.ts/\"); if [ -f \"$TEST_FILE\" ]; then npx vitest run $TEST_FILE 2>&1; fi'"
}
]
}
]
}
}
ファイルを編集するたびに、対応するテストファイルがあれば自動で実行される。テストが落ちれば即座に気づける。
Hooksの詳細な設定方法はこちらで解説している:

まとめ
Claude Codeとテストの組み合わせをまとめると:
- 既存コードへのテスト追加: ソースを読ませてから生成
- カバレッジ改善: lcovレポートを渡して穴を特定
- TDDワークフロー: テストを先に書いて実装させる
- Python/pytest: モック指示を最初から入れる
テストを書くこと自体は変わっていないが、「どこが足りないか特定する」「ボイラープレートを書く」の部分をClaude Codeに委ねることで、本当に考えるべき「テスト設計」に集中できる。
全自動化パイプラインの全体像が気になる人はこちら:

Claude Codeをまだ使ったことがない人向けの実践テクニック集はこちら:
