Metadata-Version: 2.4
Name: odoom
Version: 0.1.1
Summary: Minimal Locust users for Odoo XML-RPC and JSON-RPC
Author-email: Apik <team@apik.cloud>
License-Expression: LGPL-3.0-or-later
Project-URL: Homepage, https://github.com/apikcloud/odoom
Project-URL: Repository, https://github.com/apikcloud/odoom
Project-URL: Bug Tracker, https://github.com/apikcloud/odoom/issues
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Testing :: Traffic Generation
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: locust>=2.17
Requires-Dist: requests>=2.31
Dynamic: license-file

# odoom

Locust user classes for load testing Odoo via RPC.

## Installation

```bash
pip install odoom
```

Or directly from the GitHub repository:

```bash
pip install git+https://github.com/apikcloud/odoom.git
```

## Concepts

- Each Locust user picks a **random dataset** from the pool at startup. With one dataset, all users share it; with multiple, each user draws one independently.
- A **dataset** is a directory containing one JSON file per task. Each file holds a list of rows (list of lists).
- Tasks are executed **in order** using `@sequential_task(n)`. By default a user stops when all tasks complete; set `loop = True` to repeat indefinitely.

## Dataset structure

```
datasets/
  set_001/
    product_templates.json   # [[val, ...], ...]
    supplierinfos.json
  set_002/
    product_templates.json
    supplierinfos.json
```

## Writing a locustfile

```python
from odoom.locust import OdooJsonRpcUser, sequential_task


class CatalogUser(OdooJsonRpcUser):
    dataset_root = "./datasets"
    loop = False  # set True to repeat after all tasks complete

    @sequential_task(1)
    def import_templates(self):
        rows = self.dataset.rows_for("product_templates")
        self.odoo.load(
            model="product.template",
            fields=["id", "name", "default_code", "list_price"],
            rows=rows,
        )

    @sequential_task(2)
    def import_suppliers(self):
        rows = self.dataset.rows_for("supplierinfos")
        self.odoo.load(
            model="product.supplierinfo",
            fields=["id", "partner_id/id", "product_tmpl_id/id", "price"],
            rows=rows,
        )
```

## Configuration

Options can be set via CLI, environment variable, or `locust.conf`:

| CLI flag              | Env var                    |
|-----------------------|----------------------------|
| `--odoo-url`          | `LOCUST_ODOO_URL`          |
| `--odoo-db`           | `LOCUST_ODOO_DB`           |
| `--odoo-username`     | `LOCUST_ODOO_USERNAME`     |
| `--odoo-password`     | `LOCUST_ODOO_PASSWORD`     |
| `--odoo-dataset-root` | `LOCUST_ODOO_DATASET_ROOT` |
| `--odoo-timeout`      | `LOCUST_ODOO_TIMEOUT`      |

Example `locust.conf`:

```conf
odoo-url=https://odoo.example.com
odoo-db=mydb
odoo-username=admin
odoo-password=admin
odoo-dataset-root=./datasets
```

## Running

One-shot (each user processes its dataset once, then stops):

```bash
locust --headless -u 4 -r 4 -f locustfile.py CatalogUser
```

Looping / soak test (set `loop = True` in your user class):

```bash
locust --headless -u 4 -r 4 --run-time 30m -f locustfile.py CatalogUser
```
