Skip to content

Commit 7e02ddf

Browse files
committed
Rename test databases when running parallel Tox
When tests are executed using Tox in parallel, modify the test database names, to avoid name collisions between processes. This change renames the existing `django_db_modify_db_settings_xdist_suffix` fixture, to a generic `django_db_modify_db_settings_parallel_suffix` one, in case more scenarios/tools have to be considered in the future. It also handles projects where both `pytest-xdist` and parallel `tox` are being using, generating database names like `test_default_py37-django21_gw0`. Resolves #678.
1 parent 82de481 commit 7e02ddf

File tree

3 files changed

+71
-22
lines changed

3 files changed

+71
-22
lines changed

docs/database.rst

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -191,21 +191,43 @@ If you need to customize the location of your test database, this is the
191191
fixture you want to override.
192192

193193
The default implementation of this fixture requests the
194-
:fixture:`django_db_modify_db_settings_xdist_suffix` to provide compatibility
194+
:fixture:`django_db_modify_db_settings_parallel_suffix` to provide compatibility
195195
with pytest-xdist.
196196

197197
This fixture is by default requested from :fixture:`django_db_setup`.
198198

199+
django_db_modify_db_settings_parallel_suffix
200+
""""""""""""""""""""""""""""""""""""""""""""
201+
202+
.. fixture:: django_db_modify_db_settings_parallel_suffix
203+
204+
Requesting this fixture will add a suffix to the database name when the tests
205+
are run via `pytest-xdist`, or via `tox` in parallel mode.
206+
207+
This fixture is by default requested from
208+
:fixture:`django_db_modify_db_settings`.
209+
210+
django_db_modify_db_settings_tox_suffix
211+
"""""""""""""""""""""""""""""""""""""""
212+
213+
.. fixture:: django_db_modify_db_settings_tox_suffix
214+
215+
Requesting this fixture will add a suffix to the database name when the tests
216+
are run via `tox` in parallel mode.
217+
218+
This fixture is by default requested from
219+
:fixture:`django_db_modify_db_settings_parallel_suffix`.
220+
199221
django_db_modify_db_settings_xdist_suffix
200222
"""""""""""""""""""""""""""""""""""""""""
201223

202224
.. fixture:: django_db_modify_db_settings_xdist_suffix
203225

204226
Requesting this fixture will add a suffix to the database name when the tests
205-
are run via pytest-xdist.
227+
are run via `pytest-xdist`.
206228

207229
This fixture is by default requested from
208-
:fixture:`django_db_modify_db_settings`.
230+
:fixture:`django_db_modify_db_settings_parallel_suffix`.
209231

210232
django_db_use_migrations
211233
""""""""""""""""""""""""

pytest_django/fixtures.py

Lines changed: 44 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -33,35 +33,35 @@
3333

3434

3535
@pytest.fixture(scope="session")
36-
def django_db_modify_db_settings_xdist_suffix(request):
36+
def django_db_modify_db_settings_tox_suffix(request):
3737
skip_if_no_django()
3838

39-
from django.conf import settings
39+
tox_environment = os.environ.get("TOX_PARALLEL_ENV")
40+
if tox_environment:
41+
# Put a suffix like _py27-django21 on tox workers
42+
_set_suffix_to_test_databases(suffix=tox_environment)
4043

41-
for db_settings in settings.DATABASES.values():
42-
43-
try:
44-
test_name = db_settings["TEST"]["NAME"]
45-
except KeyError:
46-
test_name = None
4744

48-
if not test_name:
49-
if db_settings["ENGINE"] == "django.db.backends.sqlite3":
50-
return ":memory:"
51-
else:
52-
test_name = "test_{}".format(db_settings["NAME"])
45+
@pytest.fixture(scope="session")
46+
def django_db_modify_db_settings_xdist_suffix(request):
47+
skip_if_no_django()
5348

49+
xdist_suffix = getattr(request.config, "slaveinput", {}).get("slaveid")
50+
if xdist_suffix:
5451
# Put a suffix like _gw0, _gw1 etc on xdist processes
55-
xdist_suffix = getattr(request.config, "slaveinput", {}).get("slaveid")
56-
if test_name != ":memory:" and xdist_suffix is not None:
57-
test_name = "{}_{}".format(test_name, xdist_suffix)
52+
_set_suffix_to_test_databases(suffix=xdist_suffix)
5853

59-
db_settings.setdefault("TEST", {})
60-
db_settings["TEST"]["NAME"] = test_name
54+
55+
@pytest.fixture(scope="session")
56+
def django_db_modify_db_settings_parallel_suffix(
57+
django_db_modify_db_settings_tox_suffix,
58+
django_db_modify_db_settings_xdist_suffix,
59+
):
60+
skip_if_no_django()
6161

6262

6363
@pytest.fixture(scope="session")
64-
def django_db_modify_db_settings(django_db_modify_db_settings_xdist_suffix):
64+
def django_db_modify_db_settings(django_db_modify_db_settings_parallel_suffix):
6565
skip_if_no_django()
6666

6767

@@ -153,6 +153,31 @@ def _disable_native_migrations():
153153
settings.MIGRATION_MODULES = DisableMigrations()
154154

155155

156+
def _set_suffix_to_test_databases(suffix):
157+
if not suffix:
158+
return
159+
160+
from django.conf import settings
161+
162+
for db_settings in settings.DATABASES.values():
163+
164+
try:
165+
test_name = db_settings["TEST"]["NAME"]
166+
except KeyError:
167+
test_name = None
168+
169+
if not test_name:
170+
if db_settings["ENGINE"] == "django.db.backends.sqlite3":
171+
continue
172+
test_name = "test_{}".format(db_settings["NAME"])
173+
174+
if test_name == ":memory:":
175+
continue
176+
177+
db_settings.setdefault("TEST", {})
178+
db_settings["TEST"]["NAME"] = "{}_{}".format(test_name, suffix)
179+
180+
156181
# ############### User visible fixtures ################
157182

158183

pytest_django/plugin.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
from .fixtures import django_db_keepdb # noqa
2222
from .fixtures import django_db_createdb # noqa
2323
from .fixtures import django_db_modify_db_settings # noqa
24+
from .fixtures import django_db_modify_db_settings_parallel_suffix # noqa
25+
from .fixtures import django_db_modify_db_settings_tox_suffix # noqa
2426
from .fixtures import django_db_modify_db_settings_xdist_suffix # noqa
2527
from .fixtures import _live_server_helper # noqa
2628
from .fixtures import admin_client # noqa

0 commit comments

Comments
 (0)