pytest-api-kit
Pragmatic scaffolding for API smoke & regression tests. Pytest + Requests, with the observability your team actually wants: schema validation, snapshot drift detection, and HTML reports that surface endpoint / status / payload shape / description per test.
繁體中文 | English
Why another API test thing?
Most API test stacks lean one of two ways:
- Plugin overkill —
pytest-plugin-X+pytest-plugin-Y+ mock servers + schema registry → weeks before you write the first assertion. - Bare assertions — raw
requests.get+assert resp.status_code == 200→ ships fast but silent to "200 but array is empty" bugs, no drift detection, ugly reports.
pytest-api-kit sits in the middle. It's a scaffolding repo with a tiny shared core (api_kit package) you clone and adapt. You own the test code; the kit just hands you the plumbing:
- APIClient with auto-logging (method, status, size, duration, payload shape)
- Zero-dep schema validator — one DSL, 10 lines to read, no jsonschema / pydantic
- Snapshot drift detection — auto-saves response baseline on pass, diffs on fail (added/removed fields, type changes, ±30% size drift)
- Pytest-HTML extras — adds Endpoint / Status / API Time / Size / Payload shape / Description columns to the built-in report
- Empty-array warning — flags "200 OK but
items: []" responses automatically (silent breakage class)
60-second demo
git clone https://github.com/kao273183/pytest-api-kit.git
cd pytest-api-kit
python3 -m venv venv && source venv/bin/activate
pip install -e .
pytest examples/ -v
open report.html
You'll see 8 tests pass against httpbin.org, and report.html carries a row per test with these columns filled in:
| Test | Endpoint | Status | API Time | Size | Payload | Description |
|---|---|---|---|---|---|---|
| test_get_200 | GET /get | 200 | 180ms | 298B | args={0k} headers={7k} origin="..." url="..." | GET /get — simplest possible smoke check. |
Try breaking one of the example assertions — the failure report shows an API_CHANGED diagnosis if the response shape drifted, or silence if it didn't (meaning it's a real bug).
What's in the box
pytest-api-kit/
├── src/api_kit/ ← the tiny shared core (install once, import everywhere)
│ ├── client.py ← APIClient: auto-logs every request, tracks last_* attrs
│ ├── schema.py ← S DSL + validate()
│ ├── snapshot.py ← save/load/compare JSON response baselines
│ ├── fixtures.py ← make_client_fixture(), make_auth_client_fixture()
│ └── reporters/
│ └── html_extras.py ← pytest-html hooks (Endpoint/Status/Size/Payload/Description)
├── examples/
│ ├── conftest.py ← copy this as your starting point
│ └── test_example.py ← 8 tests demoing every feature
├── templates/ ← starter files for a new project
│ ├── conftest.py
│ ├── pytest.ini
│ └── config/env.template.yaml
└── docs/
├── getting-started.md ← 30-minute guide
├── schema-cookbook.md ← 10 common response shapes → schema DSL
└── adapters/
├── bearer-token.md
├── oauth.md
└── otp-flow.md
5 features that matter in practice
1. Payload-shape logging catches the silent bug class
A passing test that says status_code == 200 is worth less than you think. This is a real bug we've seen:
GET /api/v1/news → 200 OK
{"total": 42, "records": [], "categories": [...]}
^^^
← records is empty, but the test passed
api_kit logs this automatically:
[INFO] GET https://api.example.com/api/v1/news -> 200 (142 bytes, 95.3ms)
[INFO] payload: total=42 records[]=0⚠ categories[]=5
[WARN] ⚠ empty fields: records
And the ⚠ tag shows up in the HTML report so you don't miss it.
2. Schema validation with no library to learn
from api_kit import validate, S
validate(resp.json(), {
"total": S.int,
"records": S.list_of({
"id": S.any,
"title": S.str,
"published_at": S.optional,
}),
})
That's the whole DSL. Error messages carry JSON paths:
SchemaError: $.records[0].title: expected str, got NoneType = None
3. Snapshot drift = free API change detection
Saved per-endpoint JSON baseline (field paths + types + response size). When a test fails, diff against baseline to classify:
- Fields added/removed/type-changed → probably a spec change, not a bug
- Response size ±30% AND ±2KB → probably data volume change
- No diff → probably a real bug
You can wire this into pytest-html's Diagnosis column (see examples/conftest.py).
4. HTML report that's actually useful
pytest-html's default table is method/status — fine for a one-off run, useless for a team dashboard. With the extras plugin you get:
- Endpoint — one column click-sortable
- Status — colour-coded (2xx/4xx/5xx)
- API Time — colour-coded by latency threshold (green/yellow/red)
- Size — bytes/KB auto-formatted
- Payload — monospace shape summary + ⚠ for empties (full summary on hover)
- Description — first line of docstring + full
__doc__as tooltip
5. Drop-in replacement for raw requests
Every call keeps the familiar requests.Response API. You can graduate an existing test suite over gradually — just swap requests.get for api_client.get.
Install
# From git (current)
pip install git+https://github.com/kao273183/pytest-api-kit.git
# From PyPI (planned, not yet published)
pip install pytest-api-kit
Adapting to your auth flow
Three adapter docs for the common cases:
- Bearer token —
docs/adapters/bearer-token.md(OAuth2 client credentials, API keys, etc.) - OAuth with refresh —
docs/adapters/oauth.md(with mid-session token refresh) - OTP / multi-step login —
docs/adapters/otp-flow.md(SMS/Email OTP + AES payload, real-world extracted from production)
Extras (optional, shipped as separate repos)
pytest-api-kit-aws— ECS Fargate + ECR + S3 + CloudFront one-click deploy (CloudFormation + shell scripts)pytest-api-kit-dashboard— Cognito-gated self-service trigger panel for non-engineers to kick off tests and browse reports
Contributing
git clone https://github.com/kao273183/pytest-api-kit.git
cd pytest-api-kit
python3 -m venv venv && source venv/bin/activate
pip install -e ".[dev]"
pytest
PRs welcome, especially:
- More auth adapters (SAML, JWT custom claims, mTLS)
- Additional reporter backends (Allure, Slack, Discord)
- Language-agnostic reporter JSON export
License
MIT — see LICENSE.
Extracted from a production UAT API test framework, stripped of domain-specific bits, and rebuilt to be adoptable by any team in a weekend.
中文版
為什麼又一個 API 測試工具?
API 測試工具通常兩極化:
- Plugin 地獄 — 堆 10 個 pytest plugin + mock server + schema registry,設定好要一週
- 裸 requests —
assert status == 200寫很快,但抓不到「200 但陣列空」這種靜默 bug,報告也難看
pytest-api-kit 在兩者中間。是腳手架 repo(不是 plugin),你 clone 下來改幾個 config 就能寫第一個 test。共用核心(api_kit package)薄薄一層,其他都是你自己的 code。
核心功能
APIClient— 每次呼叫自動 log method/status/size/duration/payload shape- 零依賴 schema validator —
validate(data, {"id": S.str, ...}),10 行讀完 - Snapshot drift 偵測 — 自動存 baseline,比對出欄位增減、型別改變、±30% size 漂移
- Pytest-HTML 多欄位報告 — Endpoint / Status / API Time / Size / Payload / Description
- 空陣列警告 — 「回 200 但
data[]是空的」自動標 ⚠
快速開始
git clone https://github.com/kao273183/pytest-api-kit.git
cd pytest-api-kit
python3 -m venv venv && source venv/bin/activate
pip install -e .
pytest examples/ -v
open report.html
適用場景
- 30+ API 的新創 — 工程師想寫 smoke test 但不想花一週設基礎設施
- QA 從手測升級到自動化 — 照 example 改就能擴充
- 架構師要 daily UAT regression — 開箱即用 CI / Docker / Slack 通知
延伸模組(獨立 repo)
pytest-api-kit-aws— ECS Fargate 一鍵部署(CloudFormation)pytest-api-kit-dashboard— Cognito 自助觸發面板(給非工程使用者)
授權
MIT。歡迎 fork 改用在任何公司專案,不用留版權宣告(但提一下很開心)。
Metadata
Release files for pytest-api-kit 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| pytest_api_kit-0.1.0.tar.gz | 20.0 kB | Without provenance | Details for pytest_api_kit-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| pytest_api_kit-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for pytest_api_kit-0.1.0-py3-none-any.whl |
Total release size: 37.0 kB
Release files / pytest_api_kit-0.1.0.tar.gz
| Download URL | pytest_api_kit-0.1.0.tar.gz |
|---|---|
| Size | 20.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a8dccc6023bf33d05d8f3a26c3ce0e6f13c2721be5e98a95c706a286b502efc4
|
|
BLAKE2b-256 checksum How to use checksums |
f797287834b16d17b12282f8d4f210eceb8fcdfd78e79fa4e701966b2446d465
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.9.6
|
Release files / pytest_api_kit-0.1.0-py3-none-any.whl
| Download URL | pytest_api_kit-0.1.0-py3-none-any.whl |
|---|---|
| Size | 17.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6d8c9437d0f6c7cc6f71962b3de6a206b9919ca6201e4e9474a1f3c38e910792
|
|
BLAKE2b-256 checksum How to use checksums |
b9bf504276784a8ca9252493dbf63223b70a8befa94caa64e095114ee277d698
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.9.6
|
Security for pytest-api-kit 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.