Pragmatic scaffolding for API smoke / regression tests — zero-dep schema, snapshot drift, HTML reports, AWS ECS deploy.
Project description
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 改用在任何公司專案,不用留版權宣告(但提一下很開心)。
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_api_kit-0.1.0.tar.gz.
File metadata
- Download URL: pytest_api_kit-0.1.0.tar.gz
- Upload date:
- Size: 20.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a8dccc6023bf33d05d8f3a26c3ce0e6f13c2721be5e98a95c706a286b502efc4
|
|
| MD5 |
d0eec10137830667503b82349df862b9
|
|
| BLAKE2b-256 |
f797287834b16d17b12282f8d4f210eceb8fcdfd78e79fa4e701966b2446d465
|
File details
Details for the file pytest_api_kit-0.1.0-py3-none-any.whl.
File metadata
- Download URL: pytest_api_kit-0.1.0-py3-none-any.whl
- Upload date:
- Size: 17.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6d8c9437d0f6c7cc6f71962b3de6a206b9919ca6201e4e9474a1f3c38e910792
|
|
| MD5 |
3f461ada666f1bc5867b9a167d9c0d09
|
|
| BLAKE2b-256 |
b9bf504276784a8ca9252493dbf63223b70a8befa94caa64e095114ee277d698
|