1Hepi is a command-line tool for testing REST APIs using YAML-based configurations. It supports environment management, dynamic data generation, and response chaining, allowing you to build complex test scenarios where results/state from one request is used in subsequent ones.
2
3## Installation
4
5```bash
6go install github.com/mitjafelicijan/hepi@latest
7```
8
9## Basic example
10
11```yaml
12environments:
13 local:
14 host: http://localhost:8080
15
16requests:
17 login:
18 method: POST
19 url: "{{host}}/v1/auth/login"
20 description: "Authenticate and get a token"
21 headers:
22 Content-Type: "application/json"
23 json:
24 username: "admin"
25 password: "secret-password"
26
27 get_profile:
28 method: GET
29 url: "{{host}}/v1/profile"
30 description: "Fetch user profile using the token from login"
31 headers:
32 Authorization: "Bearer {{login.token}}"
33 Accept: "application/json"
34
35groups:
36 auth_flow:
37 - login
38 - get_profile
39```
40
41## CLI Usage
42
43### Basic Usage
44
45```bash
46# Execute a single request
47hepi -env staging -file test.yaml -req create_user
48
49# Execute multiple requests
50hepi -env staging -file test.yaml -req login,get_profile
51
52# Use a specific environment
53hepi -env staging -file test.yaml -req get_status
54```
55
56### Executing Groups
57
58```bash
59# Execute a group of requests defined in the YAML
60hepi -env staging -file test.yaml -group auth_flow
61```
62
63### Overriding Variables
64
65You can override variables defined in the `environments` section by passing them as system environment variables. This is useful for CI/CD or quick testing.
66
67```bash
68# Override the 'host' variable from the command line
69host=https://httpbin.org go run main.go generators.go -env test -file test.yaml -group all
70```
71
72### Variable Precedence
73
74When resolving `{{variable}}` placeholders, Hepi follows a strict lookup sequence. The first source to return a value wins.
75
761. **System Environment**: Variables set in your shell or passed as command-line prefixes (e.g., `HOST=... go run ...`).
772. **Local `.env` File**: Variables loaded from a `.env` file in the current directory. These provide defaults that can be overridden by the system environment.
783. **YAML Environment**: Variables defined within the specific `environments` block selected via the `-env` flag.
794. **Persistent State**: Key-value pairs stored in `.hepi.json` from previous request executions (accessed via `{{request_name.path.to.key}}`).
80
81#### Rationale
82
83This hierarchy (System > .env > YAML > State) is designed for **dynamic runtime overrides**:
84* **Non-destructive testing**: Override values from the CLI without modifying the static YAML configuration.
85* **Secret Management**: Keep sensitive credentials in the environment or `.env` files to avoid committing them to version control.
86* **CI/CD Integration**: Automated pipelines can inject configuration via environment variables which seamlessly take precedence.
87
88
89### Options
90
91* `-env`: The environment to use.
92* `-file`: Path to the YAML configuration file.
93* `-req`: Comma-separated list of request names to execute.
94* `-group`: The name of a request group to execute.
95* `-headers`: Show response headers in the output.
96* `-timeout`: Request timeout duration (default: 10s).
97* `-state`: Path to state file (default: .hepi.json).
98
99## Core Concepts
100
101### Environments
102
103Environments allow you to define variables that change based on the target (e.g., local development vs. production). Each environment is a map of key-value pairs.
104
105### Requests
106
107Requests are the individual API calls you want to perform. Each request specifies its method, URL, headers, and body (`json`, `form`, or `files`).
108
109### Groups
110
111Groups are ordered lists of requests. Executing a group runs the requests in the specified sequence.
112
113## Configuration Syntax
114
115The configuration is defined in a YAML file (e.g., `test.yaml`).
116
117### Substitution Syntax
118
119Hepi uses two types of placeholders:
120
1211. **`{{variable}}`**: Used for substituting values from:
122 * **Environment Variables**: Values from a `.env` file (loaded automatically if present) or system environment variables.
123 * **Config Variables**: Variables defined in the `environments` section of the YAML.
124 * **Request State**: Values captured from previous request responses (e.g., `{{login_req.token}}`). For arrays, use index notation (e.g., `{{setup_project.members.0.name}}`).
1252. **`[[generator]]`**: Used for generating dynamic data (e.g., `[[email]]`, `[[name]]`).
1263. **`[[oneof: a, b, c]]`**: Randomly selects one of the provided values.
127
128### State Chaining (Persistence)
129
130When a request is executed, its response (if it's JSON) is stored in a local `.hepi.json` file. This allows subsequent requests to reference any field from the response using the `{{request_name.path.to.field}}` syntax.
131
132## Data Generators (Fakers)
133
134Hepi includes a wide range of generators for dynamic data. You can use these by wrapping the tag in double brackets, e.g., `[[email]]`.
135
136| Tag | Description |
137| :--- | :--- |
138| `name` | Random full name |
139| `first_name` | Random first name |
140| `last_name` | Random last name |
141| `email` | Random email address |
142| `username` | Random username |
143| `password` | Random password |
144| `url` | Random URL |
145| `phone` | Random phone number |
146| `int` | Random integer (0 - 1,000,000) |
147| `datetime` | Random time string |
148| `date` | Random date string |
149| `timestamp` | Random timestamp |
150| `uuid_hyphenated`| Random hyphenated UUID |
151| `jwt` | Random JWT token |
152| `ipv4` | Random IPv4 address |
153| `amount` | Random currency amount |
154| `word` | Random word |
155| `sentence` | Random sentence |
156| `real_address` | Random real-world address |
157| `cc_number` | Random credit card number |
158| `cc_type` | Random credit card type |
159| `domain_name` | Random domain name |
160| `ipv6` | Random IPv6 address |
161| `mac_address` | Random MAC address |
162| `unix_time` | Random Unix timestamp |
163| `currency` | Random currency code |
164
165*Refer to `generators.go` for the latest implementation of these functions.*
166
167## State File
168
169Hepi stores response data in `.hepi.json` in the current directory. This file is updated after every successful request that returns a JSON response. You can inspect this file or delete it to clear the "memory" of previous requests.
170
171## Examples
172
173### 1. Basic Request with Environments
174
175This example shows how to define multiple environments and a simple GET request that uses the `host` variable.
176
177```yaml
178environments:
179 local:
180 host: http://localhost:8080
181 api_key: "dev-key-123"
182 staging:
183 host: https://api.staging.example.com
184 api_key: "staging-key-456"
185
186requests:
187 get_status:
188 method: GET
189 url: "{{host}}/v1/status"
190 description: "Check API health status"
191 headers:
192 X-API-Key: "{{api_key}}"
193 Accept: "application/json"
194```
195
196To execute this request:
197```bash
198hepi -env local -file test.yaml -req get_status
199```
200
201### 2. Request with Dynamic Data
202
203Demonstrating the use of various generators to create a new resource with randomized data.
204
205```yaml
206environments:
207 local:
208 host: http://localhost:8080
209
210requests:
211 create_user:
212 method: POST
213 url: "{{host}}/v1/users"
214 description: "Create a new user with random profile data"
215 headers:
216 Content-Type: "application/json"
217 json:
218 name: "[[name]]"
219 email: "[[email]]"
220 username: "[[username]]"
221 password: "[[password]]"
222 profile:
223 bio: "[[sentence]]"
224 age: "[[int]]"
225 website: "[[url]]"
226 phone: "[[phone]]"
227```
228
229To execute this request:
230```bash
231hepi -env local -file test.yaml -req create_user
232```
233
234### 3. State Chaining (Persistence)
235
236This scenario shows a full authentication flow where the token from the login response is reused in a subsequent request.
237
238```yaml
239environments:
240 local:
241 host: http://localhost:8080
242
243requests:
244 login:
245 method: POST
246 url: "{{host}}/v1/auth/login"
247 description: "Authenticate and get a token"
248 headers:
249 Content-Type: "application/json"
250 json:
251 username: "admin"
252 password: "secret-password"
253
254 get_profile:
255 method: GET
256 url: "{{host}}/v1/profile"
257 description: "Fetch user profile using the token from login"
258 headers:
259 Authorization: "Bearer {{login.token}}"
260 Accept: "application/json"
261
262groups:
263 auth_flow:
264 - login
265 - get_profile
266```
267
268To execute this group:
269```bash
270hepi -env local -file test.yaml -group auth_flow
271```
272
273### 4. Form Data and Query Parameters
274
275Example of a complex search request using both query parameters and URL-encoded form data.
276
277```yaml
278environments:
279 local:
280 host: http://localhost:8080
281
282requests:
283 search_items:
284 method: POST
285 url: "{{host}}/v1/search"
286 description: "Search items with filters and pagination"
287 params:
288 q: "[[word]]"
289 page: "1"
290 limit: "20"
291 sort: "[[oneof: asc, desc]]"
292 form:
293 category: "[[oneof: electronics, books, clothing]]"
294 include_out_of_stock: "true"
295 min_price: "[[int]]"
296```
297
298To execute this request:
299```bash
300hepi -env local -file test.yaml -req search_items
301```
302
303### 5. Nested JSON, Arrays, and Header Subscriptions
304
305Showing how to handle complex data structures and reuse specific nested fields from previous state.
306
307```yaml
308environments:
309 local:
310 host: http://localhost:8080
311
312requests:
313 setup_project:
314 method: POST
315 url: "{{host}}/v1/projects"
316 description: "Create a complex project structure"
317 headers:
318 Content-Type: "application/json"
319 json:
320 title: "Project [[word]]"
321 settings:
322 visibility: "[[oneof: public, private]]"
323 notifications:
324 email: true
325 push: false
326 tags: ["active", "[[word]]", "[[word]]"]
327 members:
328 - name: "[[name]]"
329 role: "owner"
330 - name: "[[name]]"
331 role: "editor"
332
333 verify_project:
334 method: GET
335 url: "{{host}}/v1/projects/{{setup_project.id}}"
336 description: "Verify the project creation using the ID from the previous request"
337 headers:
338 X-Project-Owner: "{{setup_project.members.0.name}}"
339 Accept: "application/json"
340```
341
342To execute these requests:
343```bash
344hepi -env local -file test.yaml -req setup_project,verify_project
345```
346
347### 6. File Uploads (Multipart)
348
349Hepi supports uploading files using `multipart/form-data`. You can combine `form` fields and `files` in the same request.
350
351```yaml
352environments:
353 local:
354 host: http://localhost:8080
355
356requests:
357 upload_document:
358 method: POST
359 url: "{{host}}/v1/upload"
360 description: "Upload a document with metadata"
361 form:
362 category: "financial"
363 priority: "high"
364 files:
365 document: "path/to/report.pdf"
366 thumbnail: "path/to/image.png"
367```
368
369To execute this request:
370```bash
371hepi -env local -file test.yaml -req upload_document
372```
373
374### 7. CRUD Operations (PUT, PATCH, DELETE)
375
376Hepi supports all standard HTTP methods. This example shows how to update and delete resources.
377
378```yaml
379requests:
380 update_user:
381 method: PUT
382 url: "{{host}}/v1/users/{{create_user.id}}"
383 json:
384 name: "[[name]]"
385 active: true
386
387 patch_settings:
388 method: PATCH
389 url: "{{host}}/v1/users/{{create_user.id}}/settings"
390 form:
391 theme: "dark"
392 notifications: "enabled"
393
394 delete_user:
395 method: DELETE
396 url: "{{host}}/v1/users/{{create_user.id}}"
397 params:
398 force: "true"
399```
400
401To execute these requests:
402```bash
403hepi -env local -file test.yaml -req update_user,patch_settings,delete_user
404```