pytest-django
pytest-django copied to clipboard
Add option to not setup Django in pytest_load_initial_conftests already
pytest-django sets up Django in pytest_load_initial_conftests already, which requires you to use a pytest plugin yourself if you want to do anything before it, e.g. changing project settings for tests in the environment, before the settings get imported.
Using a pytest plugin has its issues though (https://github.com/pytest-dev/pytest/issues/5190).
To keep it backward compatible I think a new option could be used here, to either defer this to pytest_configure, or skip it completely (but providing a way to call it manually).
Ref: https://github.com/pytest-dev/pytest-django/pull/719
I have similar issues when trying to call django-compat-patcher setup before django.setup().
Is it necessary that django.setup() gets called so early in pytest loading system ? Isn't it psosible to put that setup later, after conftests and the likes have been loaded, so that it's easier to override that behaviour, and benefit from other plugins like pytest-pythonpath ?
Else, how about a new setting which would point to a callable to be called INSTEAD of django.setup() ? Thus this new callable could peacefully do pre/post setup tweaks around the django environement, and still benefit from other pytest-django options (like "--ds").
I could work on a patch if we agree on the best strategy here to allow pre/post django.setup() in pytest. :)
It is not really possible / easy, since you might want to use models already in your conftest etc.
A new setting might make sense though, and it's default could even be changed then in a non-backward-compatible way maybe even - after all it is easier to just call django.setup() (or a wrapper provided by pytest-django) in your conftest than the other way around.
Have you looked at #719, and the dealbreaker therein especially? (https://github.com/pytest-dev/pytest-django/pull/719/files#r277162947)
OK I see the point of having django already setup at conftest stage then.
I don't think we need to make anything backwards incompatible, this new setting ("--django-setup" ?) would defaut to "django.setup", could be changed to something else, and could be left to a special value ("null" ?) to say that no setup must occur.
Does this behaviour sound OK to you ? If so, I might have a look at a PR for this.
Sounds like a good idea in general.. it could be an "importable string" then, which should be a callable.
btw: have you seen https://pytest-django.readthedocs.io/en/latest/configuring_django.html#changing-your-app-before-django-gets-set-up (for a way to do something before django.setup)? Given that your use case appears to be a plugin, it should be trivial to use this hook then.
Yes I did use this instruction for changing app before django sets up, but since nothing is configured (no python paths, no conftests...), it forces me to keep a pytest plugin at the root of my project, or to set PYTHONPATH in advance.
I'm seeking a generic solution to this problem, and came up with this PR on Django itself, what do you think about it ? It would solve the "changing environment before django.setup()" for all test runners at once (django settings must be importable though, but imho it's not a problem): https://code.djangoproject.com/ticket/30536
I'm just thinking : why not add an option, in pytest-django, similar to that of pytest-pythonpath ? Since it sets up very early, maybe pytest-django shouldbe able to configure python paths so that settings and apps are found even in more complex source repositories.
As of now I don't know if this way of solving the problem would not be more generic: https://github.com/pytest-dev/pytest-django/issues/764
I'd also love to have a solution for this that's more lightweight than "implement an entire pytest plugin". We're running into an issue where using freezegun in our tests breaks PyMySQL. freezegun has a workaround that monkeypatches PyMySQL but by the time our tests import freezegun the database connection has already been created and it's too late.
The plugin can be quite short, but the big issue for me was that all this happens long before python paths are auto-detected, so I've opened a PR in the ticket #764 above to have early pythonpath tweaks, allowing to put django settings and early plugins wherever we want, without a need for "pip -e" or similar (but more complex) "poetry" equivalent.
@luser - would this solve your problem?
Well my experiments so far with early pythonpaths have failed, and I still encounter that issue of early patching of django, in my new projects.
So I guess the best attempt now would be to add a "--django-setup" option, which would be the dotted path of a callable to use instead of django.setup() ?
Beeing able to make pytest-django compatible with alternative SQL drivers like e.g. PyMySQL would be great. ATM there is need for a workaround.