PATH issue with pytest 'ImportError: No module named YadaYadaYada'
Solution 1:
I'm not sure why py.test does not add the current directory in the PYTHONPATH itself, but here's a workaround (to be executed from the root of your repository):
python -m pytest tests/
It works because Python adds the current directory in the PYTHONPATH for you.
Solution 2:
conftest
solution
The least invasive solution is adding an empty file named conftest.py
in the repo/
directory:
$ touch repo/conftest.py
That's it. No need to write custom code for mangling the sys.path
or remember to drag PYTHONPATH
along, or placing __init__.py
into dirs where it doesn't belong (using python -m pytest
as suggested in Apteryx's answer is a good solution though!).
The project directory afterwards:
repo
├── conftest.py
├── app.py
├── settings.py
├── models.py
└── tests
└── test_app.py
Explanation
pytest
looks for the conftest
modules on test collection to gather custom hooks and fixtures, and in order to import the custom objects from them, pytest
adds the parent directory of the conftest.py
to the sys.path
(in this case the repo
directory).
Other project structures
If you have other project structure, place the conftest.py
in the package root dir (the one that contains packages but is not a package itself, so does not contain an __init__.py
), for example:
repo
├── conftest.py
├── spam
│ ├── __init__.py
│ ├── bacon.py
│ └── egg.py
├── eggs
│ ├── __init__.py
│ └── sausage.py
└── tests
├── test_bacon.py
└── test_egg.py
src
layout
Although this approach can be used with the src
layout (place conftest.py
in the src
dir):
repo
├── src
│ ├── conftest.py
│ ├── spam
│ │ ├── __init__.py
│ │ ├── bacon.py
│ │ └── egg.py
│ └── eggs
│ ├── __init__.py
│ └── sausage.py
└── tests
├── test_bacon.py
└── test_egg.py
beware that adding src
to PYTHONPATH
mitigates the meaning and benefits of the src
layout! You will end up with testing the code from repository and not the installed package. If you need to do it, maybe you don't need the src
dir at all.
Where to go from here
Of course, conftest
modules are not just some files to help the source code discovery; it's where all the project-specific enhancements of the pytest
framework and the customization of your test suite happen. pytest
has a lot of information on conftest
modules scattered throughout their docs; start with conftest.py
: local per-directory plugins
Also, SO has an excellent question on conftest
modules: In py.test, what is the use of conftest.py files?
Solution 3:
I had the same problem. I fixed it by adding an empty __init__.py
file to my tests
directory.
Solution 4:
Yes, the source folder is not in Python's path if you cd
to the tests directory.
You have 2 choices:
-
Add the path manually to the test files, something like this:
import sys, os myPath = os.path.dirname(os.path.abspath(__file__)) sys.path.insert(0, myPath + '/../')
Run the tests with the env var
PYTHONPATH=../
.