pytest recommends including an additional directory to separate the source code within a project:
my_package
├── src # <-- no __init__.py on this layer
│ └── my_package
│ ├── __init__.py
│ └── util_module
│ ├── __init__.py
│ └── utils.py
└── tests
├── __init__.py
└── test_util_module
├── __init__.py
└── test_utils.py
Sadly, they say nothing[1] about how imports in the test code should work in such a case, which work for my IDE just fine in this naive example[2], but causes the following error with pytest:
~/my_package$ pytest
====================== test session starts ======================
platform linux -- Python 3.6.4, pytest-3.5.1, py-1.5.3, pluggy-0.6.0
rootdir: /home/user/workspace/my_package, inifile:
collected 0 items / 1 errors
============================ ERRORS =============================
___ ERROR collecting tests/test_util_module/test_utils.py ___
ImportError while importing test module '/home/user/workspace/my_package/tests/test_util_module/test_utils.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
tests/test_util_module/test_utils.py:1: in <module>
from test.test_module.some_file import starify
E ModuleNotFoundError: No module named 'my_package.util_module'
!!!! Interrupted: 1 errors during collection !!!!!
I can fix the issue by changing the import of the test to
from src.my_package.util_module.utils import starify
but then my IDE complaints about the src part being redundant, so I'd like to keep it out.
[1]: Not the case any more. As of version 3.7.3, pytest recommends the editable install also featured in @hoefling's answer at the top of its good practices.
[2]: Setup is virtualenv env -p python3.6; source env/bin/activate; pip install pytest
PYTHONPATH=".:src/"before running the tests, does that change anything?my_package, i.e. does it contain asetup.py?python my_code.pyworks, thenpython-test-runnershould just work too"? Linking library code correctly is a Tricky Problem, and any framework that tries to handle it for you will come with heavy assumptions and restrictions on how your code can be structured which may bite you much harder.