Record and replay HTTP and HTTPS interactions for httpx. Run your tests fast and offline.
replayx saves real HTTP responses to a cassette file on the first test run. Every later run reads from the cassette. No network calls. No flaky tests. No slow CI.
import httpx
from replayx import use_cassette
with use_cassette("cassettes/github.json"):
resp = httpx.get("https://api.github.com/users/octocat")
assert resp.json()["login"] == "octocat"
Full support for httpx.AsyncClient and the sync client. One library for both.
JSON cassettes need nothing beyond httpx. Add YAML with one extra.
Strip headers, query params, and bodies at record time. Commit cassettes with no leaks.
Use the patching context manager, or build a transport yourself. Your call.
Auto-named cassettes per test. Re-record a run with one flag.
Ships py.typed. Strict mypy passes. Clear, readable cassettes.
with use_cassette("cassettes/data.json"):
async with httpx.AsyncClient() as client:
resp = await client.get("https://api.example.com/data")
cassette = Cassette.load("cassettes/data.json", record_mode="once")
with httpx.Client(transport=cassette.sync_transport()) as client:
resp = client.get("https://api.example.com/data")
cassette.save()
def test_octocat(replayx_cassette):
with replayx_cassette():
resp = httpx.get("https://api.github.com/users/octocat")
assert resp.status_code == 200
| Mode | What happens |
|---|---|
| once | Replay an existing cassette. Record when none exists. A new request raises an error. |
| new_episodes | Replay matches and append new interactions. |
| none | Replay only. No network. No writes. Good for CI. |
| all | Reach the real backend and overwrite the cassette. Use to re-record. |