Cassettes: capture and replay
Cassettes record real API responses and replay them in tests — above the
transport (a client wrapping a client), so there's no HTTP
interception and they work identically over HTTP, Faraday, or in-process
execution. A cassette is a YAML file of {query, variables, response}
entries, matched on the normalized query + variables.
The workflow
# spec: replay when the cassette exists, record against `live` when not
cassette = GraphWeaver::Testing::Cassette.use("github", client: live)
result = RepoQuery.execute!(cassette, owner: "dpep", name: "graph_weaver")
-
Record — first run hits the live API and writes
spec/cassettes/github.yml(Testing.config.cassette_dirresolves bare names). -
Anonymize — cassettes hold real data; scrub before committing (below).
-
Commit — tests now run offline, fast, deterministic.
-
Re-record when the API's real behavior changes:
GRAPHWEAVER_RECORD=1 bundle exec rspec # every Cassette.use records afresh(
Testing.config.record = trueis the programmatic equivalent.)
Replaying an unrecorded request raises MissingRecording with the query
and the path — no silent fabrication.
Anonymization
Anonymizing rewrites recorded values through the same engine FakeClient uses, while preserving everything that makes the recording faithful:
| preserved | replaced |
|---|---|
| shape: keys, list lengths, null positions | strings (semantically: emails look like emails) |
enums, booleans, __typename |
numbers, dates |
| id relationships (same original id → same fake id) | the id values themselves |
Three ways to run it:
# 1. as recordings happen — assertions you write against the recording
# run hold on replay, and real data never touches disk
GraphWeaver::Testing.configure do |config|
config.schema = MySchema
config.anonymize = true
end
# 2. after the fact, per cassette
GraphWeaver::Testing::Cassette.new("spec/cassettes/github.yml").anonymize!(schema:)
# 3. the whole cassette_dir at once
rake graph_weaver:cassettes:anonymize
Anonymization needs the schema (it walks each recorded query's selections to know which values are enums, dates, ids...). Variables are NOT anonymized — they're the replay matching key; don't record with secret variables.
When to use what
- FakeClient — no recording needed; schema-correct random data. Best default for unit tests.
- Cassettes — real response shapes from a real API (pagination quirks, actual union members, servers' null habits). Best for integration-ish tests and regression pinning.
- Anonymized cassettes — cassette fidelity, committable without PII.