Declarative snapshot & reconciliation testing

Snapline for Python compares APIs, databases, and JSON fixtures as data — not imperative assertion chains. Feature parity with the Node.js edition: same 21 demo scenarios, same config shape (camelCase keys).

Python 3.10+ REST · GraphQL · SOAP SQL · NoSQL · Queues Kafka (optional) MIT License
Built by VaagaTech

Snapline for Python is an open-source integration testing framework from VaagaTech (www.vaagatech.com) — declarative test automation with feature parity to the Node.js edition.

Purpose

Integration tests often devolve into dozens of brittle field assertions. Snapline lets you declare golden snapshots and reconciliation rules in one config dict. The framework handles HTTP, auth, database queries, deep comparison, and structured diffs.

API ↔ file

Call REST, GraphQL, or SOAP and compare the response to a JSON fixture after normalization.

DB ↔ DB

Query two databases (same or different SQL) and compare rows — including NoSQL document stores.

API ↔ DB

Verify an API response matches a database row, or drive an API call from a DB row.

Fixture cases

Run many pass/fail scenarios from fixtures/cases/ with minimal per-case JSON.

Queue → poll

Publish to a message queue, then poll SQL or the filesystem for async results.

Install

pip install snapline-core

# Optional — messaging queues:
pip install snapline-messaging-adapters

From source (monorepo):

cd snapline-python
uv sync
# or editable pip install for each package under packages/

Quick example

import asyncio
from snapline.core import auth, test_suite

async def main():
    result = await test_suite("User sync", {
        "baseUrl": "https://api.example.com",
        "auth": auth.oauth2({
            "tokenUrl": "https://api.example.com/oauth/token",
            "clientId": "client-id",
            "clientSecret": "client-secret",
        }),
        "api": {
            "endpoint": "/api/v1/user/sync",
            "method": "POST",
            "expectedFile": "fixtures/expected.json",
            "ignoreFields": ["pincode"],
        },
    })
    raise SystemExit(0 if result["passed"] else 1)

asyncio.run(main())

Reconciliation pipeline

live data │ ├─ ignoreFields strip volatile fields (dot paths supported) ├─ transformations normalize dynamic values (dates, enums, etc.) ├─ dataMapping map equivalent codes across systems └─ deep compare structured diff with field paths
Next steps: Architecture · Getting Started · End-to-End Guide · 21 Demo Scenarios · Snapline Hub (optional reporting UI)