Metadata-Version: 2.4
Name: stress_tool
Version: 1.2.2
Summary: Stress test tool with statistical TPS reports based on Worker Dispatcher in Python
Project-URL: Homepage, https://github.com/yidas/python-stress-tool
Project-URL: Issues, https://github.com/yidas/python-stress-tool/issues
Author-email: Nick Tsai <myintaer@gmail.com>
License-File: LICENSE
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Requires-Python: >=3.0
Requires-Dist: openpyxl>=3.0.0
Requires-Dist: worker-dispatcher>=1.3.1
Description-Content-Type: text/markdown

<p align="center">
    <a href="https://www.python.org/psf-landing/" target="_blank">
        <img src="https://www.python.org/static/community_logos/python-logo.png" height="60px">
    </a>
    <h1 align="center">Python Stress Tool</h1>
    <br>
</p>

A lightweight, scriptable performance benchmarking tool for Python with automated TPS reporting.

[![PyPI](https://img.shields.io/pypi/v/stress-tool)](https://pypi.org/project/stress-tool/)
![](https://img.shields.io/pypi/implementation/stress-tool)



Features
--------

- *Easy to Code and Perform*

- *Ready-to-Present **TPS Report***

- ***Dynamic Load Simulation** with frequency_mode*  


---

OUTLINE
-------

- [Demonstration](#demonstration)
- [Introduction](#introduction)
- [Installation](#installation)
- [Usage](#usage)
    - [start()](#start)
    - [generate_report()](#generate_report)
    - [print()](#print)

---

DEMONSTRATION
-------------

Just write your own callback functions based on the [Worker Dispatcher](https://github.com/yidas/python-worker-dispatcher) library, then run it and generate the report file:

```python
import stress_test

def each_task(id: int, config, task, metadata):
    response = requests.get('https://your.name/reserve-api/')
    return response

def main():
    results = stress_test.start({
        'task': {
            'list': 1000,
            'function': each_task,
        }
    })
    # Generate the TPS report if the stress test completes successfully.
    if results != False:
        file_path = stress_test.generate_report(file_path='./tps-report.xlsx')
        print("Report has been successfully generated at {}".format(file_path))

if __name__ == '__main__':
    main()
```

```bash
$ python3 main.py > log.txt 2>&1 &
```

<img src="https://github.com/yidas/python-stress-tool/blob/main/img/demonstration_excel.png?raw=true" />

---

INTRODUCTION
------------

This tool generates professional TPS report based on the execution result from the [Worker Dispatcher](https://github.com/yidas/python-worker-dispatcher) library.

Dependencies:
- [worker-dispatcher](https://github.com/yidas/python-worker-dispatcher)
- openpyxl

---

INSTALLATION
------------

To install the current release:

```shell
$ pip install stress-tool
```

Import it in your Pythone code:

```python
import stress_test
```

---

USAGE
-----

By calling the `start()` method with the configuration parameters, the package will invoke [Worker Dispatcher](https://github.com/yidas/python-worker-dispatcher) to dispatch tasks, managing threading or processing based on the provided settings. Once the tasks are completed, `generate_report()` can be called to produce a TPS report based on the result of [Worker Dispatcher](https://github.com/yidas/python-worker-dispatcher).

### start()

Refers to [`worker_dispatcher.start()`](https://github.com/yidas/python-worker-dispatcher?tab=readme-ov-file#usage).

### generate_report()

An example configuration setting with all options is as follows:

```python
def generate_report(config: dict={}, worker_dispatcher: object=None, file_path: str='./tps-report.xlsx', display_intervals: bool=True, interval: float=0, use_processing: bool=False, verbose: bool=False, debug: bool=False):
```

#### config

|Option            |Type     |Deafult      |Description|
|:--               |:--      |:--          |:--        |
|raw_logs.fields   |dict     |None         |Customized field settings for the Excel **Raw Logs** sheet. See [Detailed Configuration](#raw_logsfields-detailed-configuration) below. |

#### raw_logs.fields Detailed Configuration

This setting allows you to map data from your `task()` function into custom columns in the Excel **Raw Logs** sheet.

* **Key (Column Name):** The header name that will appear in the Excel sheet.
* **Value (Data Mapping):** How to retrieve the data from the `metadata` dictionary you filled during the test. It supports two types:
    * **String:** The dictionary key name you used in `metadata['your_key']`. The tool will automatically fetch its value.
    * **Lambda function:** A function that receives the `metadata` dictionary as its argument. Use this when you need to access object properties or perform logic (e.g., `lambda metadata: metadata.get('response').status_code`).

#### Sample config

```python
import stress_tool
import requests

# task.callback function
def task(id: int, config, task, metadata):
    try:
        response = metadata['response'] = requests.get('https://your.name/path/')
        try:
            api_return_code = metadata['api_return_code'] = response.json().get('returnCode')
            return True if api_return_code == "0000" else False
        except Exception as e:
            return False
    except requests.exceptions.ConnectTimeout:
        metadata['error'] = 'ConnectTimeout'
    except requests.exceptions.ReadTimeout:
        metadata['error'] = 'ReadTimeout'
    except requests.exceptions.RequestException as e:
        metadata['error'] = type(e).__name__
    return False

# Start stress test
results = stress_tool.start({
    # 'debug': True,
    'task': {
        'list': 60,
        'function': task,
    },
})

# Generate the report
file_path = stress_tool.generate_report(config={
    'raw_logs': {
        'fields': {
            'Customized Field - HTTP code': lambda metadata: metadata.get('response').status_code,
            'Customized Field - API Return code': 'api_return_code',
            'Customized Field - Response Body': lambda metadata: metadata.get('response').text,
        }
    },
})

```

#### display_intervals

Indicates whether to generate `Intervals` sheet.

#### interval

Based on `Intervals` sheet, specifies the number of seconds for each split.

### print()

Refers to [`worker_dispatcher.print()`](https://github.com/yidas/python-worker-dispatcher/tree/main?tab=readme-ov-file#printobjects-sep--endn-filenone-flushtrue).


