Skip to main content

Requests Automation Framework

Project description

APITestka

Python License PyPI Documentation Status

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.

Translations / Other Languages: 繁體中文 | 简体中文


Table of Contents


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_requests", {
      "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, or graphql_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 so apitestka run can use them without writing Python.
  • VariableStore — a thread-safe key/value store. {{var}} placeholders inside payloads, URLs, headers, and templates resolve against it. Combine with AT_extract_and_store to 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 import (
    variable_store, render_template, extract_and_store, load_env_profile,
    fake_uuid, iter_csv_rows,
)

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,
    diff_payloads, diff_openapi_specs, RetryPolicy, retry_call,
)
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 je_api_testka.gui, 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/Intergration-Automation-Testing/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.mdTesting Guidelines).


License

MIT — see licenses/APITestka_LICENSE.


Links

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

je_api_testka-0.0.140.tar.gz (102.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

je_api_testka-0.0.140-py3-none-any.whl (142.2 kB view details)

Uploaded Python 3

File details

Details for the file je_api_testka-0.0.140.tar.gz.

File metadata

  • Download URL: je_api_testka-0.0.140.tar.gz
  • Upload date:
  • Size: 102.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.13

File hashes

Hashes for je_api_testka-0.0.140.tar.gz
Algorithm Hash digest
SHA256 f949a476be85ef590789d2368402cabc3d21df35e26b5f2898acc5811593f0dd
MD5 0a1417aca1a31979f71622c6652be9ae
BLAKE2b-256 1d3aaac9dc900b2a06e5d66fed72178dde3d2692cbda1dbf8bb93752d40808df

See more details on using hashes here.

File details

Details for the file je_api_testka-0.0.140-py3-none-any.whl.

File metadata

  • Download URL: je_api_testka-0.0.140-py3-none-any.whl
  • Upload date:
  • Size: 142.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.13

File hashes

Hashes for je_api_testka-0.0.140-py3-none-any.whl
Algorithm Hash digest
SHA256 89f777f4df8da5f082a5e3e1c735984d179f318ae034688d99253c30befbba8d
MD5 dcc47ff69f5a532d391a0f55ed6ed2c4
BLAKE2b-256 0927cc299bd2785e95a922ef53c98c61db14c8d2cc738a4885e331821144c9ff

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page