Testing

June 10, 2026 ยท View on GitHub

This project uses fast local tests for development and Docker Compose smoke tests for real Odoo compatibility.

Local gates

Run these before opening a pull request:

uv run python -m ruff check .
uv run python -m mypy src
uv run python -m pytest

Build and package checks:

rm -rf dist
uv run python -m build
uv run python -m twine check dist/*

Whitespace and patch hygiene:

git diff --check
git diff --cached --check

Real Odoo smoke tests

The smoke harness starts disposable Docker Compose projects and tears them down after each run.

Run the full matrix:

uv run --python 3.12 --with-editable . scripts/odoo_compose_smoke.py \
  --versions 16.0 17.0 18.0 19.0 \
  --timeout 360 \
  --inspector-smoke

Run one version at a time:

uv run --python 3.12 --with-editable . scripts/odoo_compose_smoke.py --versions 16.0 --timeout 360 --inspector-smoke
uv run --python 3.12 --with-editable . scripts/odoo_compose_smoke.py --versions 17.0 --timeout 360 --inspector-smoke
uv run --python 3.12 --with-editable . scripts/odoo_compose_smoke.py --versions 18.0 --timeout 360 --inspector-smoke
uv run --python 3.12 --with-editable . scripts/odoo_compose_smoke.py --versions 19.0 --timeout 360 --inspector-smoke

The current smoke checks validate:

  • disposable Odoo database bootstrap,
  • direct XML-RPC read access,
  • direct JSON-2 access for Odoo 19,
  • packaged custom addon XML install and update from tests/fixtures/odoo_addons,
  • bespoke complex record-rule diagnosis and packaged XML record-rule diagnosis,
  • MCP stdio tool/resource/prompt listing,
  • MCP read calls through XML-RPC,
  • MCP read calls through JSON-2 for Odoo 19,
  • diagnose_access as restricted users over XML-RPC, plus JSON-2 for Odoo 19,
  • Streamable HTTP MCP calls for Odoo 19,
  • MCP Inspector tools/list over stdio and HTTP,
  • teardown of Compose containers, networks, and volumes.

Multi-instance smoke

scripts/odoo_multi_instance_smoke.py boots one disposable stack (Odoo 18 by default) with three databases and runs the multi-instance MCP surface end to end:

uv run --python 3.12 --with-editable . scripts/odoo_multi_instance_smoke.py
# options: --version 18.0 --port 18269 --timeout 240 --keep-stack

It validates:

  • list_instances discovery (4 entries: 3 databases + a second account on the default instance) with credential redaction,
  • health_check instance posture (instance_count, default_instance),
  • validate โ†’ execute writes on all three instances, with distinct instance-bound approval tokens,
  • concurrent reads against all three instances (each sees only its own marker record),
  • default-instance routing when instance is omitted,
  • two accounts against the same database authenticating independently (get_odoo_profile identity check),
  • cross-instance approval-token replay rejection (and that the probe record was never created),
  • unknown-instance errors that list configured names without leaking credentials,
  • teardown of Compose containers, networks, and volumes.

Expected surface

The smoke harness expects:

  • 25 tools,
  • 5 prompts,
  • 1 direct resource,
  • 3 resource templates,
  • safe write preview and validation behavior,
  • fail-closed approved write behavior when runtime gates are absent.

If you add or remove tools, prompts, or resources, update the smoke expectations in scripts/odoo_compose_smoke.py and document the change in CHANGELOG.md.

Cleanup checks

After smoke testing, confirm there are no leftovers:

docker ps -a --filter name=mcp-odoo-smoke --format '{{.Names}}\t{{.Status}}'
docker network ls --filter name=mcp-odoo-smoke --format '{{.Name}}'
docker volume ls --filter name=mcp-odoo-smoke --format '{{.Name}}'

No output means the smoke stack cleaned up correctly.