pytest plugin for HTTP testing using JSON files
Project description
pytest-httpchain
A pytest plugin for testing HTTP endpoints.
Overview
pytest-httpchain is an integration testing framework for HTTP APIs based on httpx lib.
It aims at helping with common HTTP API testing scenarios, where user needs 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. Fixtures might help, but they are not designed for that.
- Code reviews are noisy — The actual test logic is rarely clear because of all the boilerplate and helpers, following changes gets overwhelming quickly.
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.
$ref with deep merging
Reuse arbitrary parts of your scenarios with JSONRef. Properties merge with type checking, so you can compose scenarios from shared fragments (auth flows, common headers, base URLs).
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 template expressions ({{ var }}) anywhere in your requests — substitution happens dynamically before each stage.
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
Full pytest integration
Markers, fixtures, parametrization, and other plugins work as expected. You're not locked into a separate ecosystem.
Quick Start
Create a JSON test file named like test_<name>.<suffix>.json (default suffix is http):
# conftest.py
import pytest
from datetime import datetime
@pytest.fixture
def now_utc():
return datetime.now()
{
"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": "user.name"
}
}
}
]
},
"update_user": {
"fixtures": ["now_utc"],
"request": {
"url": "https://api.example.com/users/{{ user_id }}",
"method": "PUT",
"body": {
"json": {
"user": {
"name": "{{ user_name }}_updated",
"timestamp": "{{ str(now_utc) }}"
}
}
}
},
"response": [
{
"verify": {
"status": 200
}
}
]
},
"cleanup": {
"always_run": true,
"request": {
"url": "https://api.example.com/cleanup",
"method": "POST"
}
}
}
}
Scenario we created:
- common data context is seeded with the first variable
user_id - get_user
url is assembled usinguser_idvariable from common data context
HTTP GET call is made
we verify the call returned code 200
assuming JSON body is returned, we extract a value by JMESPath expressionuser.nameand save it to common data context underuser_namekey - update_user
now_utcfixture value is injected into common data context
url is assembled usinguser_idvariable from common data context
we create JSON body in place using values from common data context, note thatnow_utcis converted to string in place
HTTP PUT call with body is made
we verify the call returned code 200 - cleanup
finalizing call meant for graceful exit
always_runparameter means this stage will be executed regardless of errors in previous stages
For detailed usage guide see the full documentation.
Installation
Install normally via package manager of your choice from PyPi:
pip install pytest-httpchain
or directly from Github, in case you need a particular ref:
pip install 'git+https://github.com/aeresov/pytest-httpchain@main'
Configuration
- Test file discovery is based on this name pattern:
test_<name>.<suffix>.json. Thesuffixis configurable as pytest ini option, default value is http. $refinstructions can point to other files; absolute and relative paths are supported. You can limit the depth of relative path traversal usingref_parent_traversal_depthini option, default value is 3.- Template expressions support list/dict comprehensions. You can limit the maximum comprehension length using
max_comprehension_lengthini option, default value is 50000. - Parallel stage iterations (repeat/foreach) have a safety limit configurable via
max_parallel_iterationsini option, default value is 10000.
MCP Server
pytest-httpchain includes an MCP (Model Context Protocol) server to aid AI code assistants.
Setup
Install the MCP server config and Claude Code skill into your project:
uvx pytest-httpchain install --skill --mcp
Or configure manually in .mcp.json:
{
"mcpServers": {
"pytest-httpchain": {
"command": "uvx",
"args": ["pytest-httpchain", "mcp"]
}
}
}
Features
The MCP server provides:
- Scenario validation - validate test scenario and scan for possible problems
- Claude Code skill - authoring guidance for writing test scenarios
Documentation
- Full Documentation - Complete usage guide
- Changelog - Release notes
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 me a lot of elbow grease while testing.
Project details
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_httpchain-0.2.4.tar.gz.
File metadata
- Download URL: pytest_httpchain-0.2.4.tar.gz
- Upload date:
- Size: 19.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6e49269f9833592b51874d8e6c9d377a008b7341e0d51a825f4fdc5466efba46
|
|
| MD5 |
cab98467a9684125685e231dca94d972
|
|
| BLAKE2b-256 |
48e8112b360718c40822bbcfb29fa4e510104a107c26f99e63592e4d83cc17fd
|
Provenance
The following attestation bundles were made for pytest_httpchain-0.2.4.tar.gz:
Publisher:
publish.yml on aeresov/pytest-httpchain
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pytest_httpchain-0.2.4.tar.gz -
Subject digest:
6e49269f9833592b51874d8e6c9d377a008b7341e0d51a825f4fdc5466efba46 - Sigstore transparency entry: 1210914923
- Sigstore integration time:
-
Permalink:
aeresov/pytest-httpchain@dcdc59c17cddf898b6878cbe17d5f9fe861252d2 -
Branch / Tag:
refs/tags/v0.2.4 - Owner: https://github.com/aeresov
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@dcdc59c17cddf898b6878cbe17d5f9fe861252d2 -
Trigger Event:
release
-
Statement type:
File details
Details for the file pytest_httpchain-0.2.4-py3-none-any.whl.
File metadata
- Download URL: pytest_httpchain-0.2.4-py3-none-any.whl
- Upload date:
- Size: 23.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 |
c8de1c35cecdffc28d1ccc1f71debf798e0f39b1026653fca97165e98c0d6714
|
|
| MD5 |
6ac7e3992fbee1ec64fd8412d09cbb58
|
|
| BLAKE2b-256 |
110aa51ff46d9ba29a4909498776e8e63692872aa6631e82345da103f0b604ed
|
Provenance
The following attestation bundles were made for pytest_httpchain-0.2.4-py3-none-any.whl:
Publisher:
publish.yml on aeresov/pytest-httpchain
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pytest_httpchain-0.2.4-py3-none-any.whl -
Subject digest:
c8de1c35cecdffc28d1ccc1f71debf798e0f39b1026653fca97165e98c0d6714 - Sigstore transparency entry: 1210748576
- Sigstore integration time:
-
Permalink:
aeresov/pytest-httpchain@dcdc59c17cddf898b6878cbe17d5f9fe861252d2 -
Branch / Tag:
refs/tags/v0.2.4 - Owner: https://github.com/aeresov
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@dcdc59c17cddf898b6878cbe17d5f9fe861252d2 -
Trigger Event:
release
-
Statement type: