pytest plugin to record and replay ADBC database queries
Project description
pytest-adbc-replay
[ Docs ]
Record/replay testing for ADBC database queries, as a pytest plugin.
What / Why
Works like VCR.py and pytest-recording: the first run records live queries to cassette
files on disk, subsequent runs replay from those cassettes. CI tests pass with no live warehouse
connection, and query changes are visible as plain diffs in pull requests (.sql files are
human-readable and committed to version control).
Installation
pip install pytest-adbc-replay
Quick Start
For this example we'll use the DuckDB ADBC driver (no credentials needed):
pip install adbc-driver-duckdb
Mocking is flexible enough to use with any ADBC driver.
pyproject.toml — tell the plugin which drivers to intercept:
[tool.pytest.ini_options]
adbc_auto_patch = ["adbc_driver_duckdb.dbapi"]
The value is the Python module path where connect() lives — for all standard ADBC drivers this is adbc_driver_<name>.dbapi.
test_example.py — mark each test and call connect() normally:
import adbc_driver_duckdb.dbapi as duckdb
import pytest
@pytest.mark.adbc_cassette("my_query")
def test_my_query():
conn = duckdb.connect()
with conn.cursor() as cur:
cur.execute("SELECT 42 AS answer")
assert cur.fetchone() == (42,)
No conftest.py needed. The plugin intercepts duckdb.connect() automatically for tests decorated with @pytest.mark.adbc_cassette.
Record cassettes on the first run:
pytest --adbc-record=once
Replay from cassettes (default — no flag needed):
pytest
Cassette Layout
tests/cassettes/
└── my_query/
└── adbc_driver_duckdb.dbapi/
├── 000.sql # human-readable normalised SQL
├── 000.arrow # Arrow IPC result with schema metadata
└── 000.json # parameters and driver options (null when absent)
Commit the cassettes to version control — any changes appear as diffs in pull requests.
Configuration Reference
| Setting | Type | Default | Description |
|---|---|---|---|
--adbc-record |
CLI flag | none |
Record mode for this run |
adbc_cassette_dir |
ini key | tests/cassettes |
Directory to read/write cassettes |
adbc_record_mode |
ini key | none |
Persistent record mode (overridden by CLI flag) |
adbc_dialect |
ini key (linelist) | [] |
SQL dialect for normalisation. Bare value = global fallback, driver: dialect = per-driver. Empty = auto-detect. |
adbc_auto_patch |
ini key (linelist) | [] |
ADBC driver module names to auto-intercept |
adbc_scrub_keys |
ini key (linelist) | [] |
Parameter key names to redact from cassette .json files |
Minimal pyproject.toml snippet:
[tool.pytest.ini_options]
adbc_cassette_dir = "tests/cassettes"
adbc_record_mode = "none"
adbc_dialect = [] # e.g. ["adbc_driver_snowflake.dbapi: snowflake", "adbc_driver_duckdb.dbapi: duckdb"]
adbc_auto_patch = [] # e.g. ["adbc_driver_duckdb.dbapi", "adbc_driver_snowflake.dbapi"]
adbc_scrub_keys = [] # e.g. ["token password", "adbc_driver_snowflake: account_id"]
Record Modes
| Mode | Behaviour |
|---|---|
none |
Replay only. Raises CassetteMissError if cassette is absent (default). |
once |
Record if cassette absent, replay if cassette present. |
new_episodes |
Replay existing interactions, record new ones. |
all |
Re-record everything on every run. |
Scrubbing Sensitive Values
To keep credentials out of cassette files, list parameter key names in adbc_scrub_keys:
[tool.pytest.ini_options]
adbc_scrub_keys = ["token password api_key"]
Matched values become REDACTED in the .json cassette file. Per-driver form:
adbc_scrub_keys = [
"token",
"adbc_driver_snowflake: account_id warehouse",
]
For custom scrubbing logic, override the adbc_scrubber fixture in your conftest.py:
import pytest
@pytest.fixture(scope="session")
def adbc_scrubber():
def scrub(params: dict | None, driver_name: str) -> dict | None:
if not isinstance(params, dict):
return params
return {k: "REDACTED" if k.endswith("_key") else v for k, v in params.items()}
return scrub
Config scrubbing runs first; the fixture callable receives the already-config-scrubbed params.
Advanced
adbc_param_serialisers is a session-scoped fixture for registering custom parameter serialisers
for types not handled by default.
Full reference documentation: https://anentropic.github.io/pytest-adbc-replay
License
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pytest_adbc_replay-1.0.0.tar.gz.
File metadata
- Download URL: pytest_adbc_replay-1.0.0.tar.gz
- Upload date:
- Size: 20.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d74ae0a0f4afd5ef072cc70e9d1f29c60f01f9d198299a0c40ce9635e31e0c8c
|
|
| MD5 |
8489c78315f69f2d9e2b3c3e9fe30ef8
|
|
| BLAKE2b-256 |
c82270fb4c42adf9195ad7ecdae266a7ed9c7a49bc9d7700bbfd7f37e339b6d4
|
Provenance
The following attestation bundles were made for pytest_adbc_replay-1.0.0.tar.gz:
Publisher:
release.yml on anentropic/pytest-adbc-replay
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pytest_adbc_replay-1.0.0.tar.gz -
Subject digest:
d74ae0a0f4afd5ef072cc70e9d1f29c60f01f9d198299a0c40ce9635e31e0c8c - Sigstore transparency entry: 1097103220
- Sigstore integration time:
-
Permalink:
anentropic/pytest-adbc-replay@e8f53e65bbf3e5b7ba50e96b6431c97b9630d570 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/anentropic
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@e8f53e65bbf3e5b7ba50e96b6431c97b9630d570 -
Trigger Event:
push
-
Statement type:
File details
Details for the file pytest_adbc_replay-1.0.0-py3-none-any.whl.
File metadata
- Download URL: pytest_adbc_replay-1.0.0-py3-none-any.whl
- Upload date:
- Size: 25.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8d32c39c25d92bedf31d5e28b4c46bd88d3b3bc1f264b7d3c5cefe06084cb5e9
|
|
| MD5 |
b5bab4766751a26696a15559378f72db
|
|
| BLAKE2b-256 |
9f8ff25ce3abad369809fecfda3c80914f9cb63a781d6f0658eef748347e8e7f
|
Provenance
The following attestation bundles were made for pytest_adbc_replay-1.0.0-py3-none-any.whl:
Publisher:
release.yml on anentropic/pytest-adbc-replay
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pytest_adbc_replay-1.0.0-py3-none-any.whl -
Subject digest:
8d32c39c25d92bedf31d5e28b4c46bd88d3b3bc1f264b7d3c5cefe06084cb5e9 - Sigstore transparency entry: 1097103268
- Sigstore integration time:
-
Permalink:
anentropic/pytest-adbc-replay@e8f53e65bbf3e5b7ba50e96b6431c97b9630d570 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/anentropic
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@e8f53e65bbf3e5b7ba50e96b6431c97b9630d570 -
Trigger Event:
push
-
Statement type: