pytest-django
pytest-django copied to clipboard
Non-global for multiple values for DJANGO_SETTINGS_MODULE? How?
I am dealing with a fairly complicated mono-repo that defines multiple Django instances in subdirectories. Something like this:
.
├── src/
│ ├── django_instance1/
│ │ ├── app1/
│ │ │ ├── apps.py
│ │ │ ├── __init__.py
│ │ │ ├── models.py
│ │ │ ├── schema.py
│ │ │ └── views.py
│ │ ├── asgi.py
│ │ ├── __init__.py
│ │ ├── settings.py
│ │ ├── urls.py
│ │ └── wsgi.py
│ ├── django_instance2/
│ │ ├── app2/
│ │ │ ├── apps.py
│ │ │ ├── __init__.py
│ │ │ ├── models.py
│ │ │ ├── schema.py
│ │ │ └── views.py
│ │ ├── asgi.py
│ │ ├── __init__.py
│ │ ├── settings.py
│ │ ├── urls.py
│ │ └── wsgi.py
│ └── __init__.py
└── tests/
├── django_instance1_tests/
│ ├── ...
│ ├── conftest.py
│ └── __init__.py
└── django_instance2_tests/
├── ...
├── conftest.py
└── __init__.py
For reasons beyond the scope of this issue, I need to test each with different DJANGO_SETTINGS_MODULEs (e.g,. DJANGO_SETTINGS_MODULE=django_instance1.settings for tests/django_instance1_tests, DJANGO_SETTINGS_MODULE=django_instance2.settings for tests/django_instance2_tests, etc.).
How do I do this? It seems like pytest and pytest-django want one global value for DJANGO_SETTINGS_MODULE to be set at collection time.
I tried using conftest.py for each Django instance as follows:
# tests/django_instance1_tests/conftest.py
from __future__ import annotations
import pytest
@pytest.fixture(autouse=True)
def env_setup(monkeypatch):
monkeypatch.setenv("DJANGO_SETTINGS_MODULE", "django_instance1.settings")
This doesn't really work, though. Say I have a test (e.g., in tests/django_instance1_tests/test_foo.py):
from __future__ import annotations
def test_foo(settings, client) -> None:
import os
assert os.environ.get("DJANGO_SETTINGS_MODULE") == "django_instance1.settings" # yup
assert settings.DATABASES # works
client.get("...") # doesn't raise any exception
test_foo will pass, but I will get an exception like AttributeError: module 'django.core.mail' has no attribute 'outbox' on tests that are run after it.
If I use the db fixture or decorate test_foo with @pytest.mark.django_db, it will be skipped with the message no Django settings.
How do I accomplish what I need under these circumstances?