api-forge-cli 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,126 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ *.egg-info/
24
+ .installed.cfg
25
+ *.egg
26
+
27
+ # PyInstaller
28
+ *.manifest
29
+ *.spec
30
+
31
+ # Installer logs
32
+ pip-log.txt
33
+ pip-delete-this-directory.txt
34
+
35
+ # Unit test / coverage reports
36
+ htmlcov/
37
+ .tox/
38
+ .nox/
39
+ .coverage
40
+ .coverage.*
41
+ .cache
42
+ nosetests.xml
43
+ coverage.xml
44
+ *.cover
45
+ *.py,cover
46
+ .hypothesis/
47
+ .pytest_cache/
48
+
49
+ # Translations
50
+ *.mo
51
+ *.pot
52
+
53
+ # Django stuff:
54
+ *.log
55
+ local_settings.py
56
+
57
+ # Flask stuff:
58
+ instance/
59
+ .webassets-cache
60
+
61
+ # Scrapy stuff:
62
+ .scrapy
63
+
64
+ # Sphinx documentation
65
+ docs/_build/
66
+
67
+ # PyBuilder
68
+ target/
69
+
70
+ # Jupyter Notebook
71
+ .ipynb_checkpoints
72
+
73
+ # IPython
74
+ profile_default/
75
+ ipython_config.py
76
+
77
+ # pyenv
78
+ .python-version
79
+
80
+ # celery beat schedule file
81
+ celerybeat-schedule
82
+
83
+ # SageMath parsed files
84
+ *.sage.py
85
+
86
+ # Environments
87
+ .env
88
+ .venv
89
+ env/
90
+ venv/
91
+ ENV/
92
+ env.bak/
93
+ venv.bak/
94
+
95
+ # Spyder project settings
96
+ .spyderproject
97
+ .spyproject
98
+
99
+ # Rope project settings
100
+ .ropeproject
101
+
102
+ # mkdocs documentation
103
+ /site
104
+
105
+ # mypy
106
+ .mypy_cache/
107
+ .dmypy.json
108
+ dmypy.json
109
+
110
+ # Pyre type checker
111
+ .pyre/
112
+
113
+ # IDE
114
+ .idea/
115
+ .vscode/
116
+ *.swp
117
+ *.swo
118
+ *~
119
+
120
+ # OS
121
+ .DS_Store
122
+ Thumbs.db
123
+
124
+ # Project specific
125
+ *.yaml.example
126
+ test-output/
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Sanjay Sundar Murthy
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,393 @@
1
+ Metadata-Version: 2.4
2
+ Name: api-forge-cli
3
+ Version: 1.0.0
4
+ Summary: CLI tool for API testing, load testing, and mock server generation
5
+ Project-URL: Homepage, https://github.com/SanjaySundarMurthy/api-forge
6
+ Project-URL: Repository, https://github.com/SanjaySundarMurthy/api-forge
7
+ Project-URL: Issues, https://github.com/SanjaySundarMurthy/api-forge/issues
8
+ Author-email: Sanjay Sundar Murthy <sanjaysundarmurthy@gmail.com>
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: api,cli,http,load-testing,mock,rest,testing
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.9
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Topic :: Internet :: WWW/HTTP
22
+ Classifier: Topic :: Software Development :: Testing
23
+ Requires-Python: >=3.9
24
+ Requires-Dist: click>=8.0
25
+ Requires-Dist: httpx>=0.27
26
+ Requires-Dist: pyyaml>=6.0
27
+ Requires-Dist: rich>=13.0
28
+ Provides-Extra: dev
29
+ Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
30
+ Requires-Dist: pytest-cov>=5.0; extra == 'dev'
31
+ Requires-Dist: pytest>=8.0; extra == 'dev'
32
+ Requires-Dist: respx>=0.21; extra == 'dev'
33
+ Requires-Dist: ruff>=0.4; extra == 'dev'
34
+ Description-Content-Type: text/markdown
35
+
36
+ # api-forge
37
+
38
+ **CLI tool for API testing, load testing, and mock server generation.**
39
+
40
+ [![PyPI version](https://badge.fury.io/py/api-forge-cli.svg)](https://pypi.org/project/api-forge-cli/)
41
+ [![Python 3.9+](https://img.shields.io/badge/python-3.9+-blue.svg)](https://www.python.org/downloads/)
42
+ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
43
+
44
+ ---
45
+
46
+ ## Why api-forge?
47
+
48
+ Testing APIs shouldn't require heavy frameworks or complex setup. **api-forge** is a lightweight CLI tool that provides:
49
+
50
+ - **Test Suites** — Define API tests in simple YAML files
51
+ - **Assertions** — Validate status codes, headers, JSON paths, response times
52
+ - **Variable Chaining** — Extract values from responses for use in subsequent requests
53
+ - **Load Testing** — Stress test endpoints with configurable concurrency
54
+ - **Mock Server** — Spin up mock APIs from YAML for development/testing
55
+ - **Quick Requests** — cURL-like commands with pretty output
56
+
57
+ ---
58
+
59
+ ## Installation
60
+
61
+ ```bash
62
+ pip install api-forge-cli
63
+ ```
64
+
65
+ ---
66
+
67
+ ## Quick Start
68
+
69
+ ```bash
70
+ # Make a quick GET request
71
+ api-forge get https://jsonplaceholder.typicode.com/posts/1
72
+
73
+ # Run a test suite
74
+ api-forge test suite.yaml
75
+
76
+ # Load test an endpoint
77
+ api-forge load https://api.example.com/health -n 50 -d 10
78
+
79
+ # Start a mock server
80
+ api-forge mock mock.yaml
81
+
82
+ # Generate example configs
83
+ api-forge init --type test -o suite.yaml
84
+ ```
85
+
86
+ ---
87
+
88
+ ## Commands
89
+
90
+ ### `get` / `post` / `put` / `delete` — Quick Requests
91
+
92
+ ```bash
93
+ # GET request
94
+ api-forge get https://api.example.com/users
95
+
96
+ # POST with JSON body
97
+ api-forge post https://api.example.com/users -d '{"name": "Alice"}'
98
+
99
+ # With custom headers
100
+ api-forge get https://api.example.com/users -H "Authorization:Bearer token"
101
+
102
+ # PUT request
103
+ api-forge put https://api.example.com/users/1 -d '{"name": "Bob"}'
104
+
105
+ # DELETE request
106
+ api-forge delete https://api.example.com/users/1
107
+ ```
108
+
109
+ ### `test` — Run API Test Suites
110
+
111
+ ```bash
112
+ api-forge test suite.yaml
113
+ api-forge test tests/api-tests.yaml -v
114
+ ```
115
+
116
+ Test suites are defined in YAML:
117
+
118
+ ```yaml
119
+ name: "User API Tests"
120
+ base_url: "https://api.example.com"
121
+
122
+ headers:
123
+ Authorization: "Bearer {{token}}"
124
+
125
+ variables:
126
+ token: "your-api-token"
127
+
128
+ requests:
129
+ - name: "Get all users"
130
+ url: "/users"
131
+ method: GET
132
+ assertions:
133
+ - type: status
134
+ expected: 200
135
+ - type: response_time
136
+ expected: 2000
137
+
138
+ - name: "Create user"
139
+ url: "/users"
140
+ method: POST
141
+ body:
142
+ name: "Alice"
143
+ email: "alice@example.com"
144
+ assertions:
145
+ - type: status
146
+ expected: 201
147
+ - type: json_path
148
+ path: "id"
149
+ expected: 1
150
+ variables:
151
+ new_user_id: "id" # Extract for next request
152
+
153
+ - name: "Get created user"
154
+ url: "/users/{{new_user_id}}"
155
+ method: GET
156
+ assertions:
157
+ - type: status
158
+ expected: 200
159
+ ```
160
+
161
+ ### `load` — Load Testing
162
+
163
+ ```bash
164
+ # Quick load test
165
+ api-forge load https://api.example.com/health -n 50 -d 30
166
+
167
+ # From config file
168
+ api-forge load -c loadtest.yaml
169
+ ```
170
+
171
+ | Option | Description |
172
+ |--------|-------------|
173
+ | `-n, --concurrency` | Number of concurrent connections (default: 10) |
174
+ | `-d, --duration` | Test duration in seconds (default: 10) |
175
+ | `--rps` | Requests per second limit (0 = unlimited) |
176
+ | `-c, --config` | Load test config YAML file |
177
+
178
+ Load test config:
179
+
180
+ ```yaml
181
+ url: "https://api.example.com/users"
182
+ method: GET
183
+ concurrency: 100
184
+ duration_seconds: 60
185
+ requests_per_second: 500
186
+ timeout: 10.0
187
+ headers:
188
+ Authorization: "Bearer token"
189
+ ```
190
+
191
+ **Output includes:**
192
+ - Total requests, success/failure counts
193
+ - Requests per second achieved
194
+ - Latency percentiles (min, avg, p50, p95, p99, max)
195
+ - Status code distribution
196
+ - Error samples
197
+
198
+ ### `mock` — Mock Server
199
+
200
+ ```bash
201
+ # Start mock server from config
202
+ api-forge mock mock.yaml
203
+
204
+ # Custom port
205
+ api-forge mock mock.yaml -p 3000
206
+
207
+ # Default server (returns 404 for all)
208
+ api-forge mock
209
+ ```
210
+
211
+ Mock server config:
212
+
213
+ ```yaml
214
+ name: "Test API"
215
+ port: 8000
216
+ cors: true
217
+
218
+ endpoints:
219
+ - path: "/health"
220
+ method: GET
221
+ status: 200
222
+ body:
223
+ status: "healthy"
224
+
225
+ - path: "/users"
226
+ method: GET
227
+ status: 200
228
+ headers:
229
+ X-Total-Count: "100"
230
+ body:
231
+ - id: 1
232
+ name: "Alice"
233
+ - id: 2
234
+ name: "Bob"
235
+
236
+ - path: "/users"
237
+ method: POST
238
+ status: 201
239
+ body:
240
+ id: 3
241
+ message: "Created"
242
+
243
+ - path: "/slow"
244
+ method: GET
245
+ status: 200
246
+ delay_ms: 2000 # Simulate latency
247
+ body:
248
+ message: "Slow response"
249
+
250
+ - path: "/users/*" # Wildcard matching
251
+ method: GET
252
+ status: 200
253
+ body:
254
+ id: 1
255
+ name: "User"
256
+ ```
257
+
258
+ ### `init` — Generate Examples
259
+
260
+ ```bash
261
+ api-forge init --type test -o suite.yaml
262
+ api-forge init --type load -o loadtest.yaml
263
+ api-forge init --type mock -o mock.yaml
264
+ ```
265
+
266
+ ---
267
+
268
+ ## Assertion Types
269
+
270
+ | Type | Description | Example |
271
+ |------|-------------|---------|
272
+ | `status` | HTTP status code | `expected: 200` or `expected: [200, 201]` |
273
+ | `header` | Header value contains | `header: Content-Type`, `expected: json` |
274
+ | `body_contains` | Body contains string | `expected: "success"` |
275
+ | `json_path` | JSON path equals value | `path: user.id`, `expected: 123` |
276
+ | `body_regex` | Body matches regex | `expected: "\\d{5}"` |
277
+ | `response_time` | Max response time (ms) | `expected: 500` |
278
+
279
+ ---
280
+
281
+ ## Variable Substitution
282
+
283
+ Use `{{variable_name}}` syntax in URLs, headers, and body:
284
+
285
+ ```yaml
286
+ variables:
287
+ api_key: "secret123"
288
+ user_id: "456"
289
+
290
+ requests:
291
+ - name: "Get user"
292
+ url: "/users/{{user_id}}"
293
+ headers:
294
+ X-API-Key: "{{api_key}}"
295
+ ```
296
+
297
+ **Extract variables from responses** for request chaining:
298
+
299
+ ```yaml
300
+ requests:
301
+ - name: "Login"
302
+ url: "/auth/login"
303
+ method: POST
304
+ body:
305
+ username: "admin"
306
+ password: "secret"
307
+ variables:
308
+ auth_token: "token" # Extract $.token from response
309
+
310
+ - name: "Protected endpoint"
311
+ url: "/protected"
312
+ headers:
313
+ Authorization: "Bearer {{auth_token}}"
314
+ ```
315
+
316
+ ---
317
+
318
+ ## Examples
319
+
320
+ ### Full Test Suite with Chaining
321
+
322
+ ```yaml
323
+ name: "E-commerce API"
324
+ base_url: "https://api.shop.example.com"
325
+
326
+ requests:
327
+ - name: "Create product"
328
+ url: "/products"
329
+ method: POST
330
+ body:
331
+ name: "Widget"
332
+ price: 29.99
333
+ assertions:
334
+ - type: status
335
+ expected: 201
336
+ variables:
337
+ product_id: "id"
338
+
339
+ - name: "Get product"
340
+ url: "/products/{{product_id}}"
341
+ assertions:
342
+ - type: json_path
343
+ path: "name"
344
+ expected: "Widget"
345
+
346
+ - name: "Delete product"
347
+ url: "/products/{{product_id}}"
348
+ method: DELETE
349
+ assertions:
350
+ - type: status
351
+ expected: 204
352
+ ```
353
+
354
+ ### Load Test with Detailed Config
355
+
356
+ ```yaml
357
+ url: "https://api.example.com/search"
358
+ method: POST
359
+ concurrency: 200
360
+ duration_seconds: 120
361
+ requests_per_second: 1000
362
+ timeout: 5.0
363
+ headers:
364
+ Content-Type: "application/json"
365
+ body:
366
+ query: "test"
367
+ limit: 10
368
+ ```
369
+
370
+ ---
371
+
372
+ ## Development
373
+
374
+ ```bash
375
+ git clone https://github.com/SanjaySundarMurthy/api-forge.git
376
+ cd api-forge
377
+ pip install -e ".[dev]"
378
+ pytest tests/ -v
379
+ ```
380
+
381
+ ---
382
+
383
+ ## Author
384
+
385
+ **Sanjay Sundar Murthy**
386
+ - GitHub: [@SanjaySundarMurthy](https://github.com/SanjaySundarMurthy)
387
+ - Email: sanjaysundarmurthy@gmail.com
388
+
389
+ ---
390
+
391
+ ## License
392
+
393
+ MIT License — see [LICENSE](LICENSE) for details.