Open woutervh opened 8 months ago
I'm often in need of utilities, constants and FactoryBoy
factories which I prefer to place in utils.py
, constants.py
and factories.py
. I don't want to mix them up in a conftest, which I purely reserve for fixtures. I never import from other tests and/or confest.py
__init__.py
is present?utils
and constants
?In my experience a lot of python devs struggle with what directories should be a module and what not. Many times I see init.py splattered in almost every directory, and weird imports because virtually every directory is a toplevel module.
usually I make 1 toplevel module in src (which should not contain an init.py
src/
foo/__init__
and a helpers-module for re-usable test-code
tests/
_helpers/__init__.py
in conftest.py, pytest_plugins will add modules to the PYTHONPATH.
pytest_plugins = [
"_helpers",
]
From the moment there is an init-file in the test, tests-discovery changes from a flat namespace to a hierarchical where "tests" is the toplevel module.
pytest then treats it as a module, imports it in a hacky way,
and people are tempted to mix test-code and reusable test-code, because 'it works'.
or worse create depencencies between tests. (fixing that in my current project)
The disadvantage of not having an init is you cannot 2 test-files with the same filename in different dirs. But this can be fixed byb changing the import-mode to importlib, which is recommende for new projectd
see https://docs.pytest.org/en/7.1.x/explanation/goodpractices.html#choosing-an-import-mode
so in pyproject.toml
[tool.pytest.ini_options]
addopts = "--import-mode=importlib"
2) re-usable test-code: create a python-module in a subdir of tests Personally I settled on a "_helpers"-module "tests/_helpers/init.py" Then add it as a pytest-plugin, that will automaticallly put it on the PYTHONPATH
pytest_plugins = [
"_helpers",
]
but changing the import-mode no longer adds the tests-dir to PYTHONPATH, so this import will stop working
solution: https://github.com/pytest-dev/pytest/issues/8964 see also https://github.com/pmeier/pytest-import (addon no longer needed with #8964 above)
[tool.pytest.ini_options]
addopts = "--import-mode=importlib "
cache_dir = "var/cache/pytest"
testpaths = ["tests"]
pythonpath = ["tests"] # add tests-dir back to PYTHONPATH,
IMHO making imports from one test-file into another test-file not possible, is a feature, not a bug. So I'm currently considering a src-sublevel, for complete symmetry with src:
pythonpath = ["tests/src"] # add tests/src to PYTHONPATH,
with module tests/src/_helpers/init.py
then only python-modules in src-dirs
What's up with the init-files under tests?
with an init-file one turns the tests-directory into a python-module which should be avoided, because it changes the behaviour of your tests-discovery.
People usually add an init because they want to import some code from one test-file into another,
which it something one should not do. There are proper solution for re-usable test-code.