Skip to content

Commit

Permalink
Add support for distributed run
Browse files Browse the repository at this point in the history
When tests are distributed, a copy of the database is created for each worker at the start of the test session. This is useful to avoid concurrent access to the same database, which can lead to deadlocks. The provided database is therefore used only as template. At the end of the tests, all the created databases are dropped.
  • Loading branch information
lmignon committed Oct 7, 2024
1 parent 095ca9f commit 4e02c7f
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 1 deletion.
2 changes: 2 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ You can use the ``ODOO_RC`` environment variable using an odoo configuration fil
export ODOO_RC=/path/to/odoo/config.cfg
pytest ...

The plugin is also compatible with distributed run provided by the `pytest-xdist <https://pypi.org/project/pytest-xdist/>`_ library. When tests are distributed, a copy of the database is created for each worker at the start of the test session.
This is useful to avoid concurrent access to the same database, which can lead to deadlocks. The provided database is therefore used only as template. At the end of the tests, all the created databases are dropped.

Known issues
------------
Expand Down
29 changes: 28 additions & 1 deletion pytest_odoo.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import signal
import sys
import threading
from contextlib import contextmanager
from pathlib import Path
from typing import Optional

Expand Down Expand Up @@ -112,6 +113,30 @@ def load_http(request):
signal.signal(signal.SIGINT, signal.default_int_handler)


@contextmanager
def _worker_db_name():
# This method ensure that if tests are ran in a distributed way
# thanks to the use of pytest-xdist addon, each worker will use
# a specific copy of the initial database to run their tests.
# In this way we prevent deadlock errors.
xdist_worker = os.getenv("PYTEST_XDIST_WORKER")
original_db_name = db_name = odoo.tests.common.get_db_name()
try:
if xdist_worker:
db_name = f"{original_db_name}-{xdist_worker}"
ret = os.system(f"psql -lqt | cut -d \| -f 1 | grep -w {db_name}")
if ret == 0:
os.system(f"dropdb {db_name}")
os.system(f"createdb -T {original_db_name} {db_name}")
odoo.tools.config["db_name"] = db_name
yield db_name
finally:
if db_name != original_db_name:
odoo.sql_db.close_db(db_name)
os.system(f"dropdb {db_name}")
odoo.tools.config["db_name"] = original_db_name


@pytest.fixture(scope='session', autouse=True)
def load_registry():
# Initialize the registry before running tests.
Expand All @@ -123,7 +148,9 @@ def load_registry():
# Finally we enable `testing` flag on current thread
# since Odoo sets it when loading test suites.
threading.current_thread().testing = True
odoo.registry(odoo.tests.common.get_db_name())
with _worker_db_name() as db_name:
odoo.registry(db_name)
yield


@pytest.fixture(scope='module', autouse=True)
Expand Down

0 comments on commit 4e02c7f

Please sign in to comment.