--- name: testing-skill description: Record, rewrite, and debug VCR cassettes for HTTP recordings. Use when running tests with --record-mode, verifying cassette playback, or inspecting request/response bodies in YAML cassettes. allowed-tools: Bash(uv run pytest *), Bash(uv run python .claude/skills/testing-skill/parse_cassette.py *), Bash(source .env && uv run pytest *), Bash(git diff *) --- # Pytest VCR Workflow Use this skill when recording or re-recording VCR cassettes for tests, or when debugging cassette contents. ## Prerequisites - Verify `.env` exists: `test -f .env && echo 'ok' || echo 'missing'` - Missing API keys will cause clear test errors at runtime ## Important flags - `--record-mode=rewrite` : Record cassettes (works for both new and existing) - `--lf` : Run only the last failed tests - `-vv` : Verbose output - `--tb=line` : Short traceback output - `-k=""` : Run tests matching the given substring expression ## Recording Cassettes ### Step 1: Record cassettes ```bash source .env && uv run pytest path/to/test.py::test_function_name -v --tb=line --record-mode=rewrite ``` Multiple tests can be specified: ```bash source .env && uv run pytest path/to/test.py::test_one path/to/test.py::test_two -v --tb=line --record-mode=rewrite ``` ### Step 2: Verify recordings Run the same tests WITHOUT `--record-mode` to verify cassettes play back correctly: ```bash source .env && uv run pytest path/to/test.py::test_function_name -vv --tb=line ``` ### Step 3: Review snapshots If tests use [`snapshot()`](https://github.com/15r10nk/inline-snapshot) assertions: - The test run in Step 2 auto-fills snapshot content - Review the generated snapshot files to ensure they match expected output - You only review - don't manually write snapshot contents - Snapshots capture what the test actually produced, additional to explicit assertions ## Parsing Cassettes Parse VCR cassette YAML files to inspect request/response bodies without dealing with raw YAML. ### Usage ```bash uv run python .claude/skills/testing-skill/parse_cassette.py [--interaction N] ``` ### Examples ```bash # Parse all interactions in a cassette uv run python .claude/skills/testing-skill/parse_cassette.py tests/models/cassettes/test_foo/test_bar.yaml # Parse only interaction 1 (0-indexed) uv run python .claude/skills/testing-skill/parse_cassette.py tests/models/cassettes/test_foo/test_bar.yaml --interaction 1 ``` ### Output For each interaction, shows: - Request: method, URI, parsed body (truncated base64) - Response: status code, parsed body (truncated base64) Base64 strings longer than 100 chars are truncated for readability. ## Full Workflow Example ```bash # 1. Record cassette source .env && uv run pytest tests/models/test_openai.py::test_chat_completion -v --tb=line --record-mode=rewrite # 2. Verify playback and fill snapshots source .env && uv run pytest tests/models/test_openai.py::test_chat_completion -vv --tb=line # 3. Review test code diffs (excludes cassettes) git diff tests/ -- ':!**/cassettes/**' # 4. List new/changed cassettes (name only - use parse_cassette.py to inspect) git diff --name-only tests/ -- '**/cassettes/**' # 5. Inspect cassette contents if needed uv run python .claude/skills/testing-skill/parse_cassette.py tests/models/cassettes/test_openai/test_chat_completion.yaml ```