jpskill.com
🛠️ 開発・MCP コミュニティ

pytest-recording

Work with pytest-recording (VCR.py) for recording and replaying HTTP interactions in tests. Use when writing VCR tests, managing cassettes, configuring VCR options, filtering sensitive data, or debugging recorded HTTP responses.

⚡ おすすめ: コマンド1行でインストール(60秒)

下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。

🍎 Mac / 🐧 Linux
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o pytest-recording.zip https://jpskill.com/download/17569.zip && unzip -o pytest-recording.zip && rm pytest-recording.zip
🪟 Windows (PowerShell)
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/17569.zip -OutFile "$d\pytest-recording.zip"; Expand-Archive "$d\pytest-recording.zip" -DestinationPath $d -Force; ri "$d\pytest-recording.zip"

完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。

💾 手動でダウンロードしたい(コマンドが難しい人向け)
  1. 1. 下の青いボタンを押して pytest-recording.zip をダウンロード
  2. 2. ZIPファイルをダブルクリックで解凍 → pytest-recording フォルダができる
  3. 3. そのフォルダを C:\Users\あなたの名前\.claude\skills\(Win)または ~/.claude/skills/(Mac)へ移動
  4. 4. Claude Code を再起動

⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。

🎯 このSkillでできること

下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。

📦 インストール方法 (3ステップ)

  1. 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
  2. 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
  3. 3. 展開してできたフォルダを、ホームフォルダの .claude/skills/ に置く
    • · macOS / Linux: ~/.claude/skills/
    • · Windows: %USERPROFILE%\.claude\skills\

Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。

詳しい使い方ガイドを見る →
最終更新
2026-05-18
取得日時
2026-05-18
同梱ファイル
1

📖 Skill本文(日本語訳)

※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。

pytest-recording (VCR.py) テスト

概要

pytest-recording は VCR.py をラップし、HTTP のやり取りを YAML カセットとして記録することで、ライブ API 呼び出しなしで決定性のあるテストを可能にします。

クイックリファレンス

テストの実行

# すべてのテストを実行 (既存のカセットを使用)
uv run pytest tests/

# 単一のテストを実行
uv run pytest tests/test_module.py::test_function

# 新しいレスポンスですべてのカセットを書き換える
uv run pytest tests/ --vcr-record=rewrite

# 欠落しているカセットのみを記録
uv run pytest tests/ --vcr-record=new_episodes

# VCR を無効にする (ライブリクエストを行う)
uv run pytest tests/ --disable-recording

記録モード

モード フラグ 動作
none --vcr-record=none 再生のみ、カセットがない場合は失敗
once (デフォルト) カセットが存在しない場合に記録
new_episodes --vcr-record=new_episodes 新しいリクエストを記録、既存のものを保持
all --vcr-record=all 常に記録、既存のものを上書き
rewrite --vcr-record=rewrite すべてのカセットを削除して再記録

VCR テストの作成

VCR を使用した基本的なテスト:

import pytest

@pytest.mark.vcr()
def test_api_call():
    response = my_api_function()
    assert response.status_code == 200

カスタムカセット名:

@pytest.mark.vcr("custom_cassette_name.yaml")
def test_with_custom_cassette():
    pass

複数のカセット:

@pytest.mark.vcr("cassette1.yaml", "cassette2.yaml")
def test_with_multiple_cassettes():
    pass

conftest.py での VCR 設定

vcr_config フィクスチャは VCR の動作を制御します:

@pytest.fixture(scope="module")
def vcr_config():
    return {
        # 記録から機密ヘッダーをフィルタリング
        "filter_headers": ["authorization", "api-key", "x-api-key"],

        # クエリパラメータをフィルタリング
        "filter_query_parameters": ["key", "api_key", "token"],

        # これらの基準でリクエストをマッチング
        "match_on": ["method", "scheme", "host", "port", "path", "query"],

        # 特定のホストを無視 (記録しない)
        "ignore_hosts": ["localhost", "127.0.0.1"],

        # 記録モード
        "record_mode": "once",
    }

機密データのフィルタリング

LLM プロバイダーの場合、認証をフィルタリングします:

@pytest.fixture(scope="module")
def vcr_config():
    return {
        "filter_headers": [
            "authorization",      # OpenAI, Anthropic
            "api-key",            # Azure OpenAI
            "x-api-key",          # Anthropic
            "x-goog-api-key",     # Google AI
        ],
        "filter_query_parameters": ["key"],
    }

レスポンス処理

高度な処理には pytest_recording_configure を使用します:

def pytest_recording_configure(config, vcr):
    vcr.serializer = "yaml"
    vcr.decode_compressed_response = True

    # レスポンスヘッダーをサニタイズ
    def sanitize_response(response):
        response['headers']['Set-Cookie'] = 'REDACTED'
        return response

    vcr.before_record_response = sanitize_response

カセットの場所

カセットはデフォルトで tests/cassettes/ に保存され、テストモジュールごとに整理されます:

tests/
├── cassettes/
│   └── test_module/
│       └── test_function.yaml
└── test_module.py

デバッグ

カセットが見つからない

"Can't find cassette" でテストが失敗する場合:

  1. --vcr-record=once を使用して実行し、欠落しているカセットを作成します
  2. カセットのパスがテストの場所と一致することを確認します
  3. カセットファイルが存在し、有効な YAML であることを確認します

リクエストのミスマッチ

VCR がリクエストをマッチングできない場合:

  1. vcr_configmatch_on 基準を確認します
  2. カセット内のリクエストの詳細と実際のリクエストを比較します
  3. --vcr-record=new_episodes を使用して、欠落しているやり取りを追加します

古いカセット

API レスポンスが変更された場合:

  1. 特定のカセットファイルを削除してテストを再実行します
  2. または、--vcr-record=rewrite を使用してすべてのカセットを更新します

カセットの内容を表示

# カセットファイルを表示
cat tests/cassettes/test_module/test_function.yaml

# カセット内の特定のコンテンツを検索
grep -r "error" tests/cassettes/

新しい LLM プロバイダーの追加

新しいプロバイダーを追加する場合:

  1. 認証ヘッダーを特定します (プロバイダーのドキュメントを確認)
  2. vcr_configfilter_headers にヘッダーを追加します
  3. クエリパラメータ認証を filter_query_parameters に追加します
  4. --vcr-record=once でテストしてカセットを作成します
  5. カセットにシークレットが含まれていないことを確認します

一般的なプロバイダー認証:

プロバイダー フィルタリングするヘッダー
OpenAI authorization
Anthropic x-api-key, authorization
Azure OpenAI api-key
Google AI x-goog-api-key
Cohere authorization

ベストプラクティス

  1. シークレットをコミットしない: 常に認証ヘッダー/パラメータをフィルタリングします
  2. わかりやすいテスト名を使用する: カセット名はテスト名から派生します
  3. カセットを小さく保つ: テストに必要なものだけをモックします
  4. PR でカセットを確認する: 機密データの漏洩がないか確認します
  5. 定期的に再生成する: API レスポンスは時間の経過とともに変化する可能性があります
  6. スコープを適切に使用する: 共有フィクスチャには scope="module" を使用します
📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開

pytest-recording (VCR.py) Testing

Overview

pytest-recording wraps VCR.py to record HTTP interactions as YAML cassettes, enabling deterministic tests without live API calls.

Quick Reference

Running Tests

# Run all tests (uses existing cassettes)
uv run pytest tests/

# Run a single test
uv run pytest tests/test_module.py::test_function

# Rewrite all cassettes with fresh responses
uv run pytest tests/ --vcr-record=rewrite

# Record only missing cassettes
uv run pytest tests/ --vcr-record=new_episodes

# Disable VCR (make live requests)
uv run pytest tests/ --disable-recording

Recording Modes

Mode Flag Behavior
none --vcr-record=none Only replay, fail if no cassette
once (default) Record if no cassette exists
new_episodes --vcr-record=new_episodes Record new requests, keep existing
all --vcr-record=all Always record, overwrite existing
rewrite --vcr-record=rewrite Delete and re-record all cassettes

Writing VCR Tests

Basic test with VCR:

import pytest

@pytest.mark.vcr()
def test_api_call():
    response = my_api_function()
    assert response.status_code == 200

Custom cassette name:

@pytest.mark.vcr("custom_cassette_name.yaml")
def test_with_custom_cassette():
    pass

Multiple cassettes:

@pytest.mark.vcr("cassette1.yaml", "cassette2.yaml")
def test_with_multiple_cassettes():
    pass

VCR Configuration in conftest.py

The vcr_config fixture controls VCR behavior:

@pytest.fixture(scope="module")
def vcr_config():
    return {
        # Filter sensitive headers from recordings
        "filter_headers": ["authorization", "api-key", "x-api-key"],

        # Filter query parameters
        "filter_query_parameters": ["key", "api_key", "token"],

        # Match requests by these criteria
        "match_on": ["method", "scheme", "host", "port", "path", "query"],

        # Ignore certain hosts (don't record)
        "ignore_hosts": ["localhost", "127.0.0.1"],

        # Record mode
        "record_mode": "once",
    }

Filtering Sensitive Data

For LLM providers, filter authentication:

@pytest.fixture(scope="module")
def vcr_config():
    return {
        "filter_headers": [
            "authorization",      # OpenAI, Anthropic
            "api-key",            # Azure OpenAI
            "x-api-key",          # Anthropic
            "x-goog-api-key",     # Google AI
        ],
        "filter_query_parameters": ["key"],
    }

Response Processing

Use pytest_recording_configure for advanced processing:

def pytest_recording_configure(config, vcr):
    vcr.serializer = "yaml"
    vcr.decode_compressed_response = True

    # Sanitize response headers
    def sanitize_response(response):
        response['headers']['Set-Cookie'] = 'REDACTED'
        return response

    vcr.before_record_response = sanitize_response

Cassette Location

Cassettes are stored in tests/cassettes/ by default, organized by test module:

tests/
├── cassettes/
│   └── test_module/
│       └── test_function.yaml
└── test_module.py

Debugging

Cassette Not Found

If tests fail with "Can't find cassette":

  1. Run with --vcr-record=once to create missing cassettes
  2. Check cassette path matches test location
  3. Verify cassette file exists and is valid YAML

Request Mismatch

If VCR can't match requests:

  1. Check match_on criteria in vcr_config
  2. Compare request details in cassette vs actual request
  3. Use --vcr-record=new_episodes to add missing interactions

Stale Cassettes

When API responses change:

  1. Delete specific cassette file and re-run test
  2. Or use --vcr-record=rewrite to refresh all cassettes

View Cassette Contents

# View a cassette file
cat tests/cassettes/test_module/test_function.yaml

# Search for specific content in cassettes
grep -r "error" tests/cassettes/

Adding New LLM Providers

When adding a new provider:

  1. Identify authentication headers (check provider docs)
  2. Add headers to filter_headers in vcr_config
  3. Add any query param auth to filter_query_parameters
  4. Test with --vcr-record=once to create cassettes
  5. Verify cassettes don't contain secrets

Common provider authentication:

Provider Headers to Filter
OpenAI authorization
Anthropic x-api-key, authorization
Azure OpenAI api-key
Google AI x-goog-api-key
Cohere authorization

Best Practices

  1. Never commit secrets: Always filter auth headers/params
  2. Use descriptive test names: Cassette names derive from test names
  3. Keep cassettes small: Mock only what you need to test
  4. Review cassettes in PRs: Check for sensitive data leaks
  5. Regenerate periodically: API responses may change over time
  6. Use scope appropriately: scope="module" for shared fixtures