APITestka
APITestka is a lightweight, cross-platform Python framework for automated API testing. It started as an HTTP/HTTPS / SOAP-XML / JSON request runner with reporting and a JSON-driven executor, and now ships with a much wider toolkit — variable chaining, OpenAPI / Postman / HAR / cURL importers, a record-replay proxy, security probes, parallel runners, an MCP server for Claude, and more.
Table of Contents
- Highlights
- Installation
- Quick Start
- Core Concepts
- Feature Map
- MCP Server for Claude
- Project Structure
- Optional Extras
- Development
- Contributing
- License
- Links
Highlights
| Area | What you get |
|---|---|
| Backends | requests (sync, sessions), httpx (sync + async, HTTP/2), WebSocket, SSE, GraphQL |
| Data layer | Variable store, {{var}} templating, CSV/JSON data-driven loops, env profiles, fake data |
| Assertions | Field assertions, JSON Schema, JSONPath, snapshot, structural diffs, OpenAPI contract drift, response-time SLAs |
| Connection | mTLS, proxies, DNS override, VCR-style cassette record/replay |
| Mock server | Static, dynamic, stateful, fault injection, OpenAPI-driven, Jinja templating, webhook receiver, record-replay proxy |
| Runner | Sequential & parallel execution, tag filters, dependency-aware ordering, retry policies |
| Reports | HTML / JSON / XML / JUnit / Allure / Markdown / shields.io badge / SQLite trend store / run diff |
| Integrations | Slack / Teams / Discord webhook, GitHub PR comment, cURL & HAR importers, OpenAPI / Postman importer |
| CLI / DX | Subcommand CLI, REPL, terminal summary, shell completion, scaffold |
| Security | Auth helpers (Basic / Bearer / JWT / AWS SigV4), header / CORS / rate-limit / SSRF probes, pip-audit wrapper, fuzz inputs |
| Spec inference | Test record → OpenAPI, JSON Schema inference, OpenAPI changelog |
| AI | Pluggable backend with deterministic fallback for test generation, fake data, failure classification |
| MCP | First-class Claude Code / MCP server exposing the framework as tools |
| GUI | Optional PySide6 GUI (English / 繁中 / 简中 / 日本語) plus Swagger UI embed |
| Cross-platform | Windows, macOS, Linux. Python 3.10–3.14 |
Installation
pip install je_api_testka
Optional extras (install with pip install 'je_api_testka[<extra>]'):
| Extra | Adds |
|---|---|
gui |
PySide6 GUI |
websocket |
websockets for the WebSocket wrapper |
schema |
jsonschema and jsonpath-ng for advanced assertions |
security |
pyjwt and botocore for JWT / AWS SigV4 helpers |
otel |
opentelemetry-api / opentelemetry-sdk for tracing hooks |
mcp |
mcp Python SDK for the MCP server |
Quick Start
from je_api_testka import test_api_method_requests, generate_html_report
test_api_method_requests(
"get", "https://httpbin.org/get",
result_check_dict={"status_code": 200},
)
generate_html_report("smoke")
JSON-driven equivalent (smoke.json):
{
"api_testka": [
["AT_test_api_method", {
"http_method": "get",
"test_url": "https://httpbin.org/get",
"result_check_dict": {"status_code": 200}
}],
["AT_generate_html_report", {"html_file_name": "smoke"}]
]
}
apitestka run smoke.json
Core Concepts
- Backends — every HTTP call goes through
requests_wrapper,httpx_wrapper,websocket_wrapper,sse_wrapper, orgraphql_wrapper. They share a record format. test_record_instance— a thread-safe singleton that captures every request / response. Reports, diffs, badges, and the trend store all read from it.- Executor — a command map (
AT_*keys) over Python callables. JSON action lists drive it. New features register themselves here soapitestka runcan use them without writing Python. - VariableStore — a thread-safe key/value store.
{{var}}placeholders inside payloads, URLs, headers, and templates resolve against it. Combine withAT_extract_and_storeto chain requests. - Optional dependencies — heavyweight features (WebSockets, JSON Schema, JWT, MCP) live behind extras and raise a friendly error if you call them without installing.
Feature Map
HTTP / Protocol Backends
| Backend | Function |
|---|---|
requests |
test_api_method_requests (sync, sessions) |
httpx sync |
test_api_method_httpx |
httpx async |
test_api_method_httpx_async (HTTP/2 via http2=True) |
| WebSocket | test_api_method_websocket, test_api_method_websocket_async (extra: websocket) |
| SSE | iter_sse_events, test_api_method_sse |
| GraphQL | test_api_method_graphql, test_api_method_graphql_async |
from je_api_testka import test_api_method_graphql
test_api_method_graphql(
"https://api.example.invalid/graphql",
query="query Get($id: ID!) { user(id: $id) { id name } }",
variables={"id": "42"},
)
Data Layer
from je_api_testka.data import (
variable_store, render_template, load_env_profile,
fake_uuid, iter_csv_rows,
)
from je_api_testka.data.variable_store import extract_and_store
load_env_profile("envs/dev.json") # populates variable_store
extract_and_store({"data": {"id": 7}}, "data.id", "user_id")
render_template("/users/{{user_id}}") # -> "/users/7"
for row in iter_csv_rows("data/users.csv"):
variable_store.set("email", row["email"])
test_api_method_requests("post", "https://x.invalid/login", json=row)
Executor commands: AT_set_variable, AT_get_variable, AT_clear_variables,
AT_extract_and_store, AT_render_template, AT_fake_uuid, AT_fake_email,
AT_fake_word, AT_load_env_profile.
Assertions, Diffs and SLAs
from je_api_testka import (
check_json_schema, check_jsonpath, assert_snapshot,
RetryPolicy, retry_call,
)
from je_api_testka.diff import diff_payloads, diff_openapi_specs
from je_api_testka.diff.sla_check import ResponseSLA, assert_sla
check_json_schema(payload, {"type": "object", "required": ["id"]})
check_jsonpath(payload, "$.data.id", expected=7)
assert_snapshot("user-by-id", payload, ignore_keys=["timestamp"])
diff = diff_payloads(prod_response, staging_response, ignore_paths=["server_time"])
assert_sla(records, ResponseSLA(max_ms=2000, p95_ms=1500))
Connection Layer
from je_api_testka.connection import (
ConnectionOptions, apply_to_requests_kwargs,
dns_override, Cassette, replay_or_record,
)
options = ConnectionOptions(cert=("c.crt", "c.key"),
proxies={"https": "http://proxy:8080"})
with dns_override({"api.example.invalid": "127.0.0.1"}):
test_api_method_requests("get", "https://api.example.invalid/health")
cassette = Cassette("tape.json") # offline replay-or-record
Mock Server
The bundled FlaskMockServer now supports several layered features:
| Feature | API |
|---|---|
| Static routes | flask_mock_server_instance.add_router({...}) |
| Dynamic routes | server.add_dynamic_route(...) + DynamicRouter rules |
| Stateful store | server.state (StatefulStore) |
| Fault injection | server.fault_injector.configure(latency_seconds=..., failure_probability=...) |
| OpenAPI driven | server.load_openapi(spec) |
| Templated | server.add_template_route("/x", {"msg": "{{name}}"}) |
| Webhook receive | server.add_webhook("/hook") then read server.webhook_receiver.all() |
| Record-replay | server.add_proxy("https://upstream", "tape.json") |
apitestka mock --host 0.0.0.0 --port 9000
Runner
from je_api_testka.runner import (
run_actions_parallel, filter_actions_by_tag, order_actions,
)
actions = order_actions(filter_actions_by_tag(actions, {"smoke"}))
results = run_actions_parallel(actions, max_workers=8)
Reports and Observability
from je_api_testka import (
generate_html_report, generate_json_report, generate_xml_report,
)
from je_api_testka.utils.generate_report.junit_report import generate_junit_report
from je_api_testka.utils.generate_report.allure_report import generate_allure_report
from je_api_testka.utils.generate_report.markdown_report import generate_markdown_report
from je_api_testka.utils.generate_report.badge import generate_badge
from je_api_testka.utils.generate_report.run_diff import diff_runs
from je_api_testka.utils.generate_report.trend_store import record_current_run
generate_html_report("report")
generate_junit_report("junit.xml") # GitHub Actions / Jenkins
generate_allure_report("allure-results") # `allure generate` consumable
generate_markdown_report("report.md") # Slack / GitHub-friendly
generate_badge("badge.json") # shields.io endpoint
record_current_run("trend.sqlite") # historical trend
OpenTelemetry hook (no-op when opentelemetry-api is absent):
from je_api_testka.utils.observability import instrument_request
with instrument_request("GET", "https://x.invalid"):
test_api_method_requests("get", "https://x.invalid")
Integrations
from je_api_testka.integrations import (
notify_via_webhook, post_pr_comment,
curl_to_action, convert_har,
)
from je_api_testka.cli.import_specs import convert_spec_file
notify_via_webhook("https://hooks.slack.invalid/...", summary="...", platform="slack")
post_pr_comment("acme/widget", pr_number=42, token="<gha-token>")
action = curl_to_action("curl -X POST https://api/x -d '{\"a\":1}'")
actions = convert_har("traffic.har")
actions = convert_spec_file("openapi.json", spec_format="openapi")
CLI / Developer Experience
apitestka run actions.json # or directory
apitestka create my_project
apitestka mock --port 9000
apitestka import openapi.json out.json --format openapi
apitestka repl # JSON action REPL
apitestka summary # ANSI-coloured summary
apitestka scaffold https://api/x out.json
apitestka completion bash # source >> ~/.bashrc
apitestka mcp # MCP server over stdio
Security Probes
from je_api_testka.security import (
basic_auth_header, bearer_token_header, build_jwt, aws_sigv4_headers,
scan_security_headers, cors_preflight, probe_rate_limit, probe_ssrf,
fuzz_string_inputs, run_pip_audit,
)
scan_security_headers(response_headers) # HSTS, CSP, nosniff…
cors_preflight("https://api/x", origin="https://app")
probe_rate_limit("https://api/x", burst=20)
probe_ssrf("https://api/fetch", parameter="url")
run_pip_audit() # delegates to pip-audit
OpenAPI Inference
from je_api_testka.spec import infer_schema, records_to_openapi, openapi_changelog
records_to_openapi(title="Recovered", version="0.1.0")
openapi_changelog(prev_spec, current_spec) # markdown diff
GUI
pip install 'je_api_testka[gui]'
Headless models (HistoryPanelModel, EnvManagerModel, render_side_by_side) live in
the je_api_testka.gui.* submodules (history_panel, env_manager_model, diff_viewer),
allowing tests and headless tooling to drive panels without PySide6. The actual Qt widgets
live in main_widget.py.
Locales: English, 繁體中文, 简体中文, 日本語. Switch via LanguageWrapper.reset_language(...).
Pluggable AI Backend
Default backend (NoOpAIBackend) never calls a network. Plug in your own to enable
LLM-driven test generation:
from je_api_testka.ai import AIBackend, set_ai_backend, generate_tests_from_openapi
class AnthropicBackend(AIBackend):
def complete(self, prompt, *, context=None):
... # call your provider
return llm_response_text
set_ai_backend(AnthropicBackend())
actions = generate_tests_from_openapi(my_openapi_spec) # falls back to a deterministic
# happy path if the LLM reply is
# not valid JSON
MCP Server for Claude
APITestka ships an MCP server so Claude (and any other MCP-compatible client) can drive the framework. Eight tools are exposed:
| Tool | Purpose |
|---|---|
apitestka_run_action |
Execute an action list |
apitestka_test_api |
One-shot HTTP request via requests backend |
apitestka_curl_to_action |
cURL → action JSON |
apitestka_har_import |
HAR file → action list |
apitestka_render_markdown |
Markdown report from current records |
apitestka_records_to_openapi |
Reconstruct an OpenAPI document |
apitestka_clear_records |
Wipe the test record |
apitestka_get_records |
Return successes / failures |
Install and run:
pip install 'je_api_testka[mcp]'
apitestka-mcp # or: apitestka mcp / python -m je_api_testka.mcp_server
Claude Code config (~/.claude/mcp.json):
{
"mcpServers": {
"apitestka": {
"command": "apitestka-mcp"
}
}
}
Project Structure
je_api_testka/
├── __init__.py # Public API exports
├── __main__.py # Legacy CLI entry point
├── ai/ # Pluggable AI backend + helpers
├── cli/ # apitestka CLI subcommands + REPL + completions
├── connection/ # ConnectionOptions, DNS override, Cassette
├── data/ # VariableStore, templates, faker, env profiles
├── diff/ # Response diff / contract drift / SLA
├── graphql_wrapper/ # GraphQL helper
├── gui/ # Optional PySide6 GUI + headless models
├── httpx_wrapper/ # httpx sync + async wrapper
├── integrations/ # Notifications, PR comments, importers
├── mcp_server/ # Claude / MCP server
├── pytest_plugin/ # pytest fixtures
├── requests_wrapper/ # requests wrapper
├── runner/ # Parallel runner, tag filter, dependency runner
├── security/ # Auth helpers, fuzz, header / CORS / SSRF / rate-limit / CVE
├── spec/ # OpenAPI inference / changelog
├── sse_wrapper/ # Server-Sent Events helper
├── utils/ # Executor, mock server, generators, etc.
└── websocket_wrapper/ # WebSocket wrapper
Optional Extras
pip install 'je_api_testka[websocket]'
pip install 'je_api_testka[schema]'
pip install 'je_api_testka[security]'
pip install 'je_api_testka[otel]'
pip install 'je_api_testka[mcp]'
pip install 'je_api_testka[gui]'
Development
git clone https://github.com/Integration-Automation/APITestka.git
cd APITestka
pip install -r dev_requirements.txt
pytest # full suite (~300+ tests)
CI runs the suite against Python 3.10 – 3.14 on Ubuntu, macOS, and Windows.
Contributing
See CONTRIBUTING.md. Every commit must ship with unit tests
(see CLAUDE.md → Testing Guidelines).
License
MIT — see licenses/APITestka_LICENSE.
Links
Release files for je-api-testka 0.0.145
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| je_api_testka-0.0.145.tar.gz | 109.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| je_api_testka-0.0.145-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 255.4 kB
Release files / je_api_testka-0.0.145.tar.gz
| Download URL | je_api_testka-0.0.145.tar.gz |
|---|---|
| Size | 109.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
530ffdd4ce812ceb8d448180b937cea3a5db6001e41bb29dddc3d685614c4404
|
|
BLAKE2b-256 checksum How to use checksums |
201ed85e0e42f9b7f8c93ec16fd1740e2416f4ee4d420fd59a4bc66bdcf85542
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.14
|
Release files / je_api_testka-0.0.145-py3-none-any.whl
| Download URL | je_api_testka-0.0.145-py3-none-any.whl |
|---|---|
| Size | 146.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
3b0612fe0c115f45cf76b65c177bc26a387e3750cf8c9cd8884026369ce1d19a
|
|
BLAKE2b-256 checksum How to use checksums |
0446c761901b7dede3b5641a12683f74de564dc209348552dd3cbbdc717aeeb9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.14
|