Skip to content

Commit 1e292c2

Browse files
committed
Update READMEs
1 parent f2916c2 commit 1e292c2

File tree

3 files changed

+1060
-21
lines changed

3 files changed

+1060
-21
lines changed

README.md

Lines changed: 344 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,358 @@
11
# LoadDensity
2-
A high‑performance load testing and automation tool.
3-
It supports fast user spawning, flexible templates, and generates reports in multiple formats.
4-
Designed to be cross‑platform and easy to integrate into your projects.
5-
6-
- Load automation: Quickly set up and run load tests
7-
- User templates: Simple configuration for reusable test users
8-
- Load Density scripts: Define and execute repeatable scenarios
9-
- Report generation: Export results in JSON, HTML, or XML
10-
- High throughput: Thousands of requests per second
11-
- Fast user spawning: Scale up test users instantly
12-
- Multi‑test support: Run multiple tests on a single task
13-
- Configurable test duration: Specify how long tests should run
14-
- OS independent: Works across major operating systems
15-
- Remote automation: Execute tests remotely
16-
- Project & template support: Organize and reuse test setup
2+
3+
[![Python](https://img.shields.io/pypi/pyversions/je_load_density)](https://pypi.org/project/je_load_density/)
4+
[![PyPI](https://img.shields.io/pypi/v/je_load_density)](https://pypi.org/project/je_load_density/)
5+
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6+
[![Documentation](https://readthedocs.org/projects/loaddensity/badge/?version=latest)](https://loaddensity.readthedocs.io/en/latest/)
7+
8+
**LoadDensity** is a high-performance load & stress testing automation framework built on top of [Locust](https://locust.io/). It provides a simplified wrapper around Locust's core functionality, enabling fast user spawning, flexible test configuration via templates and JSON-driven scripts, report generation in multiple formats (HTML / JSON / XML), a built-in GUI, remote execution via TCP socket server, and a callback mechanism for post-test workflows.
9+
10+
**[繁體中文](README/README_zh-TW.md)** | **[简体中文](README/README_zh-CN.md)**
11+
12+
---
13+
14+
## Features
15+
16+
- **Simplified Locust Wrapper** — Abstracts Locust's `Environment`, `Runner`, and `User` classes behind a clean, high-level API.
17+
- **Two User Types** — Supports both `HttpUser` and `FastHttpUser` (geventhttpclient-based, higher throughput).
18+
- **Fast User Spawning** — Scale to thousands of concurrent users with configurable spawn rate.
19+
- **JSON-Driven Test Scripts** — Define test scenarios as JSON files and execute them without writing Python code.
20+
- **Action Executor** — A built-in event-driven executor that maps action names to functions. Supports batch execution and file-driven execution.
21+
- **Report Generation** — Export test results in three formats:
22+
- **HTML** — Styled tables with success/failure records
23+
- **JSON** — Structured data for programmatic consumption
24+
- **XML** — Standard XML output for CI/CD integration
25+
- **Request Hook** — Automatically records every request (success and failure) with method, URL, status code, response body, headers, and errors.
26+
- **Callback Executor** — Chain a trigger function with a callback function for post-test workflows (e.g., run test then generate report).
27+
- **TCP Socket Server** — Remote execution server based on gevent. Accepts JSON commands over TCP to execute tests remotely.
28+
- **Project Scaffolding** — Auto-generate project directory structure with keyword templates and executor scripts.
29+
- **Package Manager** — Dynamically load external Python packages and register their functions into the executor at runtime.
30+
- **GUI (Optional)** — PySide6-based graphical interface with real-time log display, supporting English and Traditional Chinese.
31+
- **CLI Support** — Run tests, execute scripts, or scaffold projects directly from the command line.
32+
- **Cross-Platform** — Works on Windows, macOS, and Linux.
1733

1834
## Installation
1935

36+
### Basic (CLI & Library)
37+
38+
```bash
39+
pip install je_load_density
40+
```
41+
42+
### With GUI Support
43+
44+
```bash
45+
pip install je_load_density[gui]
46+
```
47+
48+
This installs [PySide6](https://doc.qt.io/qtforpython/) and [qt-material](https://github.com/UN-GCPDS/qt-material) for the graphical interface.
49+
50+
## Requirements
51+
52+
- Python **3.10** or later
53+
- [Locust](https://locust.io/) (installed automatically as a dependency)
54+
55+
## Quick Start
56+
57+
### 1. Using the Python API
58+
59+
```python
60+
from je_load_density import start_test
61+
62+
# Define user configuration and tasks
63+
result = start_test(
64+
user_detail_dict={"user": "fast_http_user"},
65+
user_count=50,
66+
spawn_rate=10,
67+
test_time=10,
68+
tasks={
69+
"get": {"request_url": "http://httpbin.org/get"},
70+
"post": {"request_url": "http://httpbin.org/post"},
71+
}
72+
)
73+
```
74+
75+
**Parameters:**
76+
| Parameter | Type | Default | Description |
77+
|---|---|---|---|
78+
| `user_detail_dict` | `dict` || User type configuration. `{"user": "fast_http_user"}` or `{"user": "http_user"}` |
79+
| `user_count` | `int` | `50` | Total number of simulated users |
80+
| `spawn_rate` | `int` | `10` | Number of users spawned per second |
81+
| `test_time` | `int` | `60` | Test duration in seconds. `None` for unlimited |
82+
| `web_ui_dict` | `dict` | `None` | Enable Locust Web UI, e.g. `{"host": "127.0.0.1", "port": 8089}` |
83+
| `tasks` | `dict` || HTTP method to request URL mapping |
84+
85+
### 2. Using JSON Script Files
86+
87+
Create a JSON file (`test_scenario.json`):
88+
89+
```json
90+
[
91+
["LD_start_test", {
92+
"user_detail_dict": {"user": "fast_http_user"},
93+
"user_count": 50,
94+
"spawn_rate": 10,
95+
"test_time": 5,
96+
"tasks": {
97+
"get": {"request_url": "http://httpbin.org/get"},
98+
"post": {"request_url": "http://httpbin.org/post"}
99+
}
100+
}]
101+
]
102+
```
103+
104+
Execute from Python:
105+
106+
```python
107+
from je_load_density import execute_action, read_action_json
108+
109+
execute_action(read_action_json("test_scenario.json"))
110+
```
111+
112+
### 3. Using the CLI
113+
114+
```bash
115+
# Execute a single JSON script file
116+
python -m je_load_density -e test_scenario.json
117+
118+
# Execute all JSON files in a directory
119+
python -m je_load_density -d ./test_scripts/
120+
121+
# Execute an inline JSON string
122+
python -m je_load_density --execute_str '[["LD_start_test", {"user_detail_dict": {"user": "fast_http_user"}, "user_count": 10, "spawn_rate": 5, "test_time": 5, "tasks": {"get": {"request_url": "http://httpbin.org/get"}}}]]'
123+
124+
# Scaffold a new project with templates
125+
python -m je_load_density -c MyProject
126+
```
127+
128+
### 4. Using the GUI
129+
130+
```python
131+
from je_load_density.gui.main_window import LoadDensityUI
132+
from PySide6.QtWidgets import QApplication
133+
import sys
134+
135+
app = QApplication(sys.argv)
136+
window = LoadDensityUI()
137+
window.show()
138+
sys.exit(app.exec())
139+
```
140+
141+
## Report Generation
142+
143+
After running a test, generate reports from the recorded data:
144+
145+
```python
146+
from je_load_density import (
147+
generate_html_report,
148+
generate_json_report,
149+
generate_xml_report,
150+
)
151+
152+
# HTML report — creates "my_report.html"
153+
generate_html_report("my_report")
154+
155+
# JSON report — creates "my_report_success.json" and "my_report_failure.json"
156+
generate_json_report("my_report")
157+
158+
# XML report — creates "my_report_success.xml" and "my_report_failure.xml"
159+
generate_xml_report("my_report")
160+
```
161+
162+
## Advanced Usage
163+
164+
### Action Executor
165+
166+
The executor maps string action names to callable functions. All built-in Python functions are also available.
167+
168+
```python
169+
from je_load_density import executor, add_command_to_executor
170+
171+
# Register a custom function
172+
def my_custom_action(message):
173+
print(f"Custom: {message}")
174+
175+
add_command_to_executor({"my_action": my_custom_action})
176+
177+
# Execute actions programmatically
178+
executor.execute_action([
179+
["my_action", ["Hello World"]],
180+
["print", ["Test complete"]],
181+
])
182+
```
183+
184+
**Built-in executor actions:**
185+
| Action Name | Description |
186+
|---|---|
187+
| `LD_start_test` | Start a load test |
188+
| `LD_generate_html` | Generate HTML fragments |
189+
| `LD_generate_html_report` | Generate full HTML report file |
190+
| `LD_generate_json` | Generate JSON data structure |
191+
| `LD_generate_json_report` | Generate JSON report files |
192+
| `LD_generate_xml` | Generate XML strings |
193+
| `LD_generate_xml_report` | Generate XML report files |
194+
| `LD_execute_action` | Execute a list of actions |
195+
| `LD_execute_files` | Execute actions from multiple files |
196+
| `LD_add_package_to_executor` | Dynamically load a package into the executor |
197+
198+
### Callback Executor
199+
200+
Chain a trigger function with a callback:
201+
202+
```python
203+
from je_load_density import callback_executor
204+
205+
def after_test():
206+
print("Test finished, generating report...")
207+
208+
callback_executor.callback_function(
209+
trigger_function_name="user_test",
210+
callback_function=after_test,
211+
user_detail_dict={"user": "fast_http_user"},
212+
user_count=10,
213+
spawn_rate=5,
214+
test_time=5,
215+
tasks={"get": {"request_url": "http://httpbin.org/get"}},
216+
)
217+
```
218+
219+
### TCP Socket Server (Remote Execution)
220+
221+
Start a TCP server that accepts JSON commands:
222+
223+
```python
224+
from je_load_density import start_load_density_socket_server
225+
226+
# Start server (blocking)
227+
start_load_density_socket_server(host="localhost", port=9940)
228+
```
229+
230+
Send commands from a client:
231+
232+
```python
233+
import socket, json
234+
235+
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
236+
sock.connect(("localhost", 9940))
237+
238+
command = json.dumps([
239+
["LD_start_test", {
240+
"user_detail_dict": {"user": "fast_http_user"},
241+
"user_count": 10, "spawn_rate": 5, "test_time": 5,
242+
"tasks": {"get": {"request_url": "http://httpbin.org/get"}}
243+
}]
244+
])
245+
sock.send(command.encode("utf-8"))
246+
response = sock.recv(8192)
247+
print(response.decode("utf-8"))
248+
sock.close()
249+
```
250+
251+
Send `"quit_server"` to gracefully shut down the server.
252+
253+
### Project Scaffolding
254+
255+
Generate a project with keyword templates and executor scripts:
256+
257+
```python
258+
from je_load_density import create_project_dir
259+
260+
create_project_dir(project_path="./my_tests", parent_name="LoadDensity")
261+
```
262+
263+
This creates:
264+
```
265+
my_tests/
266+
└── LoadDensity/
267+
├── keyword/
268+
│ ├── keyword1.json # FastHttpUser test template
269+
│ └── keyword2.json # HttpUser test template
270+
└── executor/
271+
├── executor_one_file.py # Execute single keyword file
272+
└── executor_folder.py # Execute all files in keyword/
20273
```
21-
pip install je_locust_wrapper
274+
275+
### Dynamic Package Loading
276+
277+
Load external packages and register their functions into the executor:
278+
279+
```python
280+
from je_load_density import executor
281+
282+
# Load a package and make its functions available as executor actions
283+
executor.execute_action([
284+
["LD_add_package_to_executor", ["my_custom_package"]]
285+
])
286+
```
287+
288+
### Test Records
289+
290+
Access raw test records programmatically:
291+
292+
```python
293+
from je_load_density import test_record_instance
294+
295+
# After running a test
296+
for record in test_record_instance.test_record_list:
297+
print(record["Method"], record["test_url"], record["status_code"])
298+
299+
for error in test_record_instance.error_record_list:
300+
print(error["Method"], error["test_url"], error["error"])
301+
302+
# Clear records
303+
test_record_instance.clear_records()
22304
```
23305

24-
## Require
306+
## Architecture
25307

26308
```
27-
python 3.9 or later
309+
je_load_density/
310+
├── __init__.py # Public API exports
311+
├── __main__.py # CLI entry point
312+
├── gui/ # PySide6 GUI (optional dependency)
313+
│ ├── main_window.py # Main window (QMainWindow)
314+
│ ├── main_widget.py # Test parameter form & log panel
315+
│ ├── load_density_gui_thread.py # Background thread for tests
316+
│ ├── log_to_ui_filter.py # Log interceptor for GUI display
317+
│ └── language_wrapper/ # i18n (English, Traditional Chinese)
318+
├── wrapper/
319+
│ ├── create_locust_env/ # Locust Environment & Runner setup
320+
│ ├── start_wrapper/ # High-level start_test() entry point
321+
│ ├── user_template/ # HttpUser & FastHttpUser wrappers
322+
│ ├── proxy/ # User proxy container & configuration
323+
│ └── event/ # Request hook (records all requests)
324+
└── utils/
325+
├── executor/ # Action executor (event-driven)
326+
├── generate_report/ # HTML, JSON, XML report generators
327+
├── test_record/ # Test record storage
328+
├── socket_server/ # TCP server for remote execution
329+
├── callback/ # Callback function executor
330+
├── project/ # Project scaffolding & templates
331+
├── package_manager/ # Dynamic package loading
332+
├── json/ # JSON file read/write utilities
333+
├── xml/ # XML structure utilities
334+
├── file_process/ # Directory file listing
335+
├── logging/ # Logger instance
336+
└── exception/ # Custom exceptions & error tags
28337
```
29338

30339
## Tested Platforms
31-
- Windows 10 ~ 11
32-
- macOS 10.15 ~ 11 Big Sur
340+
341+
- Windows 10 / 11
342+
- macOS 10.15 ~ 11 (Big Sur)
33343
- Ubuntu 20.04
34344
- Raspberry Pi 3B+
35-
- All test cases are located in the test directory
345+
346+
## License
347+
348+
This project is licensed under the [MIT License](LICENSE).
349+
350+
## Contributing
351+
352+
See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
353+
354+
## Links
355+
356+
- **PyPI**: https://pypi.org/project/je_load_density/
357+
- **Documentation**: https://loaddensity.readthedocs.io/en/latest/
358+
- **Source Code**: https://github.com/Intergration-Automation-Testing/LoadDensity

0 commit comments

Comments
 (0)