It'd be nice to do something like:
if settings.TESTING:
print("py.test is being ran")
"pytest" in sys.modules
?
You can add a setting yourself with a separate settings file for tests
I think the approaches suggested by @blueyed and @adamchainz should be sufficient if this is needed. Generally, changing the way your code works by introspecting whether or not the code is called from tests is not recommended. If this were to be done, it could be done in a general pytest way (it is not really specific to pytest-django). Thanks for the suggestion, feel free to reopen this issue if you have additional information in this issue!
Relevant example from the pytest docs Detect if running from within a pytest run:
# content of conftest.py
def pytest_configure(config):
import sys
sys._called_from_test = True
def pytest_unconfigure(config):
import sys
del sys._called_from_test
The problem is that pytest_configure
is run after settings.py
. Is there a way to run this code before settings.py
?
@axil
What is wrong with using 'pytest' in sys.modules
?
Hmm, yes, got it working, though it looks a bit hacky for me.
Another quick and dirty way to check this in settings.py is
TESTING = os.path.basename(sys.argv[0]) in ('pytest', 'py.test')
@axil
What is wrong with using'pytest' in sys.modules
?
The fact the pytest is imported does not mean that pytest
is running and the code is invoked from a test. Basically, one my import pytest
for something else. Also pytest is importing pytest
even if it just show a CLI help: pytest --help
Here is very valid use case:
I have django setting configurable with local files and variables where put various credentials and other local dev env configuration. But I want my unittests never use this credentials or specific settings to not accidentally use them on some real system (if improperly mocked) or pass/fail on local dev env configuration. Therefore I want these local settings excluded when ran with pytest.
I have something like:
import os
import os.path
import sys
from split_settings.tools import include, optional
def is_pytest_running():
return (os.getenv('PYTEST_RUNNING') == 'true' or
os.path.basename(sys.argv[0]) in ('pytest', 'py.test'))
ENVVAR_SETTINGS_PREFIX = 'MV_SERVER_'
local_settings_path = os.getenv(f'{ENVVAR_SETTINGS_PREFIX}SETTINGS', '../../../local/settings.py')
includes = [
'base.py',
'logging.py',
'custom.py',
]
if not is_pytest_running():
includes.append(optional(local_settings_path))
includes.append('envvars.py')
include(*includes)
Using os.getenv('PYTEST_RUNNING') == 'true'
is more or less clean way of doing it, but the issue is with setting this variable. Setting it in conftest.py does not work because pytest-django imports settings before conftest.py executed. Setting it in commandline when running pytest is inconvenient and also defeats the purpose: if someone forgets to set it then real credentials will be used from local dev env configuration.
os.path.basename(sys.argv[0]) in ('pytest', 'py.test')
I had to change it to os.path.basename(os.path.dirname(sys.argv[0])) in ('pytest', 'py.test')
since sys.argv[0]
was coming out as /home/project/venv/lib/python3.8/site-packages/pytest/__main__.py
.
Most helpful comment
"pytest" in sys.modules
?