pytest-dev / pytest-dev/pytest-django
Non-global for multiple values for DJANGO_SETTINGS_MODULE? How?
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 1.5k
- Forks
- 367
- PR merge metrics
- No merged PRs in 30d
Description
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?
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with tests/django_instance1_tests/conftest.py, tests/django_instance2_tests/conftest.py, and test_foo.py, then trace how pytest-django initializes settings and its db, settings, and client fixtures during collection. Done would be a documented, supported approach for separate settings modules per test subtree without skipped database tests or cross-test Django state.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- django, python
- Domain
- testing
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100