Agent skill
vcr-http-recording
VCR.py HTTP recording for Python tests. Use when testing Python code making HTTP requests, recording API responses for replay, or creating deterministic tests for external services.
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/other/vcr-http-recording
SKILL.md
VCR.py HTTP Recording
Record and replay HTTP interactions for Python tests.
Basic Setup
# conftest.py
import pytest
@pytest.fixture(scope="module")
def vcr_config():
return {
"cassette_library_dir": "tests/cassettes",
"record_mode": "once",
"match_on": ["uri", "method"],
"filter_headers": ["authorization", "x-api-key"],
"filter_query_parameters": ["api_key", "token"],
}
Basic Usage
import pytest
@pytest.mark.vcr()
def test_fetch_user():
response = requests.get("https://api.example.com/users/1")
assert response.status_code == 200
assert response.json()["name"] == "John Doe"
@pytest.mark.vcr("custom_cassette.yaml")
def test_with_custom_cassette():
response = requests.get("https://api.example.com/data")
assert response.status_code == 200
Async Support
import pytest
from httpx import AsyncClient
@pytest.mark.asyncio
@pytest.mark.vcr()
async def test_async_api_call():
async with AsyncClient() as client:
response = await client.get("https://api.example.com/data")
assert response.status_code == 200
assert "items" in response.json()
Recording Modes
@pytest.fixture(scope="module")
def vcr_config():
import os
# CI: never record, only replay
if os.environ.get("CI"):
record_mode = "none"
else:
record_mode = "new_episodes"
return {"record_mode": record_mode}
| Mode | Behavior |
|---|---|
once |
Record if missing, then replay |
new_episodes |
Record new, replay existing |
none |
Never record (CI) |
all |
Always record (refresh) |
Filtering Sensitive Data
def filter_request_body(request):
"""Redact sensitive data from request body."""
import json
if request.body:
try:
body = json.loads(request.body)
if "password" in body:
body["password"] = "REDACTED"
if "api_key" in body:
body["api_key"] = "REDACTED"
request.body = json.dumps(body)
except json.JSONDecodeError:
pass
return request
@pytest.fixture(scope="module")
def vcr_config():
return {
"filter_headers": ["authorization", "x-api-key"],
"before_record_request": filter_request_body,
}
LLM API Testing
def llm_request_matcher(r1, r2):
"""Match LLM requests ignoring dynamic fields."""
import json
if r1.uri != r2.uri or r1.method != r2.method:
return False
body1 = json.loads(r1.body)
body2 = json.loads(r2.body)
# Ignore dynamic fields
for field in ["request_id", "timestamp"]:
body1.pop(field, None)
body2.pop(field, None)
return body1 == body2
@pytest.fixture(scope="module")
def vcr_config():
return {
"custom_matchers": [llm_request_matcher],
}
Cassette File Example
# tests/cassettes/test_fetch_user.yaml
interactions:
- request:
body: null
headers:
Content-Type: application/json
method: GET
uri: https://api.example.com/users/1
response:
body:
string: '{"id": 1, "name": "John Doe"}'
status:
code: 200
version: 1
Key Decisions
| Decision | Recommendation |
|---|---|
| Record mode | once for dev, none for CI |
| Cassette format | YAML (readable) |
| Sensitive data | Always filter headers/body |
| Custom matchers | Use for LLM APIs |
Common Mistakes
- Committing cassettes with real API keys
- Using
allmode in CI (makes live calls) - Not filtering sensitive data
- Missing cassettes in git
Related Skills
msw-mocking- Frontend equivalentintegration-testing- API testing patternsllm-testing- LLM-specific patterns
Capability Details
http-recording
Keywords: record HTTP, vcr.use_cassette, record mode, capture HTTP Solves:
- Record HTTP interactions for replay
- Capture real API responses
- Create deterministic test fixtures
cassette-replay
Keywords: replay, cassette, playback, mock replay Solves:
- Replay recorded HTTP interactions
- Run tests without network access
- Ensure consistent test results
async-support
Keywords: async, aiohttp, httpx async, async cassette Solves:
- Record async HTTP clients
- Handle aiohttp and httpx async
- Test async API integrations
sensitive-data-filtering
Keywords: filter, scrub, redact, sensitive data, before_record Solves:
- Scrub API keys from cassettes
- Redact sensitive data
- Implement before_record hooks
custom-matchers
Keywords: matcher, match on, request matching, custom match Solves:
- Configure request matching rules
- Ignore dynamic request parts
- Match by method/host/path
llm-api-testing
Keywords: LLM cassette, OpenAI recording, Anthropic recording Solves:
- Record LLM API responses
- Test AI integrations deterministically
- Avoid costly API calls in tests
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
Didn't find tool you were looking for?