CLI tool for API testing, load testing, and mock server generation
Project description
api-forge
CLI tool for API testing, load testing, and mock server generation.
Why api-forge?
Testing APIs shouldn't require heavy frameworks or complex setup. api-forge is a lightweight CLI tool that provides:
- Test Suites — Define API tests in simple YAML files
- Assertions — Validate status codes, headers, JSON paths, response times
- Variable Chaining — Extract values from responses for use in subsequent requests
- Load Testing — Stress test endpoints with configurable concurrency
- Mock Server — Spin up mock APIs from YAML for development/testing
- Quick Requests — cURL-like commands with pretty output
Installation
pip install api-forge-cli
Quick Start
# Make a quick GET request
api-forge get https://jsonplaceholder.typicode.com/posts/1
# Run a test suite
api-forge test suite.yaml
# Load test an endpoint
api-forge load https://api.example.com/health -n 50 -d 10
# Start a mock server
api-forge mock mock.yaml
# Generate example configs
api-forge init --type test -o suite.yaml
Commands
get / post / put / delete — Quick Requests
# GET request
api-forge get https://api.example.com/users
# POST with JSON body
api-forge post https://api.example.com/users -d '{"name": "Alice"}'
# With custom headers
api-forge get https://api.example.com/users -H "Authorization:Bearer token"
# PUT request
api-forge put https://api.example.com/users/1 -d '{"name": "Bob"}'
# DELETE request
api-forge delete https://api.example.com/users/1
test — Run API Test Suites
api-forge test suite.yaml
api-forge test tests/api-tests.yaml -v
Test suites are defined in YAML:
name: "User API Tests"
base_url: "https://api.example.com"
headers:
Authorization: "Bearer {{token}}"
variables:
token: "your-api-token"
requests:
- name: "Get all users"
url: "/users"
method: GET
assertions:
- type: status
expected: 200
- type: response_time
expected: 2000
- name: "Create user"
url: "/users"
method: POST
body:
name: "Alice"
email: "alice@example.com"
assertions:
- type: status
expected: 201
- type: json_path
path: "id"
expected: 1
variables:
new_user_id: "id" # Extract for next request
- name: "Get created user"
url: "/users/{{new_user_id}}"
method: GET
assertions:
- type: status
expected: 200
load — Load Testing
# Quick load test
api-forge load https://api.example.com/health -n 50 -d 30
# From config file
api-forge load -c loadtest.yaml
| Option | Description |
|---|---|
-n, --concurrency |
Number of concurrent connections (default: 10) |
-d, --duration |
Test duration in seconds (default: 10) |
--rps |
Requests per second limit (0 = unlimited) |
-c, --config |
Load test config YAML file |
Load test config:
url: "https://api.example.com/users"
method: GET
concurrency: 100
duration_seconds: 60
requests_per_second: 500
timeout: 10.0
headers:
Authorization: "Bearer token"
Output includes:
- Total requests, success/failure counts
- Requests per second achieved
- Latency percentiles (min, avg, p50, p95, p99, max)
- Status code distribution
- Error samples
mock — Mock Server
# Start mock server from config
api-forge mock mock.yaml
# Custom port
api-forge mock mock.yaml -p 3000
# Default server (returns 404 for all)
api-forge mock
Mock server config:
name: "Test API"
port: 8000
cors: true
endpoints:
- path: "/health"
method: GET
status: 200
body:
status: "healthy"
- path: "/users"
method: GET
status: 200
headers:
X-Total-Count: "100"
body:
- id: 1
name: "Alice"
- id: 2
name: "Bob"
- path: "/users"
method: POST
status: 201
body:
id: 3
message: "Created"
- path: "/slow"
method: GET
status: 200
delay_ms: 2000 # Simulate latency
body:
message: "Slow response"
- path: "/users/*" # Wildcard matching
method: GET
status: 200
body:
id: 1
name: "User"
init — Generate Examples
api-forge init --type test -o suite.yaml
api-forge init --type load -o loadtest.yaml
api-forge init --type mock -o mock.yaml
Assertion Types
| Type | Description | Example |
|---|---|---|
status |
HTTP status code | expected: 200 or expected: [200, 201] |
header |
Header value contains | header: Content-Type, expected: json |
body_contains |
Body contains string | expected: "success" |
json_path |
JSON path equals value | path: user.id, expected: 123 |
body_regex |
Body matches regex | expected: "\\d{5}" |
response_time |
Max response time (ms) | expected: 500 |
Variable Substitution
Use {{variable_name}} syntax in URLs, headers, and body:
variables:
api_key: "secret123"
user_id: "456"
requests:
- name: "Get user"
url: "/users/{{user_id}}"
headers:
X-API-Key: "{{api_key}}"
Extract variables from responses for request chaining:
requests:
- name: "Login"
url: "/auth/login"
method: POST
body:
username: "admin"
password: "secret"
variables:
auth_token: "token" # Extract $.token from response
- name: "Protected endpoint"
url: "/protected"
headers:
Authorization: "Bearer {{auth_token}}"
Examples
Full Test Suite with Chaining
name: "E-commerce API"
base_url: "https://api.shop.example.com"
requests:
- name: "Create product"
url: "/products"
method: POST
body:
name: "Widget"
price: 29.99
assertions:
- type: status
expected: 201
variables:
product_id: "id"
- name: "Get product"
url: "/products/{{product_id}}"
assertions:
- type: json_path
path: "name"
expected: "Widget"
- name: "Delete product"
url: "/products/{{product_id}}"
method: DELETE
assertions:
- type: status
expected: 204
Load Test with Detailed Config
url: "https://api.example.com/search"
method: POST
concurrency: 200
duration_seconds: 120
requests_per_second: 1000
timeout: 5.0
headers:
Content-Type: "application/json"
body:
query: "test"
limit: 10
Development
git clone https://github.com/SanjaySundarMurthy/api-forge.git
cd api-forge
pip install -e ".[dev]"
pytest tests/ -v
Author
Sanjay Sundar Murthy
- GitHub: @SanjaySundarMurthy
- Email: sanjaysundarmurthy@gmail.com
License
MIT License — see LICENSE for details.
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 api_forge_cli-1.0.0.tar.gz.
File metadata
- Download URL: api_forge_cli-1.0.0.tar.gz
- Upload date:
- Size: 21.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bdcbb4966892fffff448e50d9b2a1bd067b33f9675cee9bb88e96cf2cac54e64
|
|
| MD5 |
02e101c73ec0927d2f762dbcf2f1e05a
|
|
| BLAKE2b-256 |
88eda2a2ec63037fb8340299a61178407f1bebf05edf5a5c385e9b9c34e0fd93
|
File details
Details for the file api_forge_cli-1.0.0-py3-none-any.whl.
File metadata
- Download URL: api_forge_cli-1.0.0-py3-none-any.whl
- Upload date:
- Size: 18.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0e2daf870ec540a65a3338020917dc7c6b69b3bc10a23841f80e0ac1dd80f254
|
|
| MD5 |
4d352f6bc5706964bb48ee61907f9c16
|
|
| BLAKE2b-256 |
770ccb73e5458f46d61fefe9139c47a355415d58339f0497d9419fdc49cdad68
|