Skip to content

image image image

pytest-httpchain

A pytest plugin for declarative HTTP API integration testing.

Overview

pytest-httpchain is an integration testing framework for HTTP APIs based on httpx. It helps with common HTTP API testing scenarios where you need to make several calls in specific order using data obtained along the way, like auth tokens or resource IDs.

Why pytest-httpchain?

Testing HTTP APIs with plain pytest often leads to these pain points:

  • Boilerplate accumulates — Every test repeats the same setup: create client, set headers, make request, parse response, assert. The actual test intent gets buried.
  • Data threading is manual — When one call returns a token or ID needed by the next, you end up with fragile helper functions passing state around.
  • Common patterns get copy-pasted — Auth flows, base URLs, shared headers end up duplicated across test files.
  • Code reviews are noisy — The actual test logic is rarely clear because of all the boilerplate.

pytest-httpchain offers a more structured approach.

Features

Declarative JSON Format

Test scenarios are JSON documents that describe what to test, not how. No setup code to scroll through — the request and assertions are right there.

$include / $merge / $ref with Deep Merging

Reuse arbitrary parts of your scenarios with JSON references. Properties merge with type checking, so you can compose scenarios from shared fragments (auth flows, common headers, base URLs). Use $include or $merge for better IDE support.

Multi-Stage Execution

Each scenario contains 1+ stages executed in order. One stage failure stops the chain. Use always_run for cleanup stages that should execute regardless.

Common Data Context

A key-value store persists throughout scenario execution. Variables, fixtures, and saved response data all live here. Use Jinja-style expressions ({{ var }}) anywhere in your requests.

Response Processing

  • JMESPath — Extract values from JSON responses directly
  • JSON Schema — Validate response structure against a schema
  • User functions — Call Python functions for custom extraction, verification, or authentication

Parametrization

Run stages with different parameter values, similar to pytest's @pytest.mark.parametrize.

Parallel Execution

Execute multiple requests concurrently for load testing, stress testing, or bulk operations.

Full pytest Integration

Markers, fixtures, parametrization, and other plugins work as expected. You're not locked into a separate ecosystem.

Quick Example

{
    "substitutions": [
        {"vars": {"user_id": 1}}
    ],
    "stages": {
        "get_user": {
            "request": {
                "url": "https://api.example.com/users/{{ user_id }}"
            },
            "response": [
                {"verify": {"status": 200}},
                {"save": {"jmespath": {"user_name": "name"}}}
            ]
        },
        "update_user": {
            "request": {
                "url": "https://api.example.com/users/{{ user_id }}",
                "method": "PUT",
                "body": {
                    "json": {"name": "{{ user_name }}_updated"}
                }
            },
            "response": [
                {"verify": {"status": 200}}
            ]
        }
    }
}

Installation

pip install pytest-httpchain

See Getting Started for detailed installation and configuration instructions.

AI agent support

pytest-httpchain ships a scenario validator to help AI agents (and humans) author and check test scenarios.

Validate scenario files for structure and common problems (undefined variables, variables used before they are saved, duplicate stage names, fixture conflicts, no-op verify steps, contradictory body checks); every finding carries a stable HTTPCHAINxxx diagnostic code, and it exits non-zero on failure, so it works as a CI gate:

uvx pytest-httpchain validate tests/test_login.http.json
# machine-readable output for editors / CI:
uvx pytest-httpchain validate --format json tests/test_login.http.json

These checks also run automatically at pytest collection time: semantic errors fail collection and warnings are reported, so pytest --collect-only validates your whole suite.

Add --deep for opt-in checks that import your module:func references (verifying they resolve and their call signatures match, including the injected response) and confirm referenced files/schemas exist. It imports your code, so it never runs at collection time; combine with --strict (fail on warnings) and --syspath (extra import roots):

uvx pytest-httpchain validate --deep --strict tests/test_login.http.json

Editors get as-you-type validation and autocomplete via the published JSON Schema — reference it with a $schema key in your test files.

Several read-only commands help inspect scenarios offline — emit the schema matching your installed version, resolve references, summarize the variable data-flow, or render it as a Mermaid diagram:

uvx pytest-httpchain schema > scenario.schema.json
uvx pytest-httpchain resolve tests/test_login.http.json
uvx pytest-httpchain show tests/test_login.http.json
uvx pytest-httpchain graph tests/test_login.http.json

Thanks

This project was inspired by Tavern and pytest-play.

httpx does comms. Pydantic keeps structure. simpleeval powers templates. pytest-order sorts chain. pytest-datadir saved a lot of elbow grease while testing.