["python","python-3.x","pytest"]
pytest cannot find module

I am following the pytest good practices or at least I think I am. However, pytest cannot find my module. It seems not to include the current directory in its PYTHONPATH. The source file: def add(x, y): return x + y The test file: import pytest from junk.ook import add def test_add_true(): assert add(1, 1) == 2 And the shell output with a Python 3 virtual environment called "p3". p3; pwd /home/usr/tmp/junk p3; ls total 0 0 junk/ 0 tests/ p3; ls junk total 4.0K 4.0K ook.py 0 __init__.py p3; ls tests total 4.0K 4.0K test_ook.py 0 __pycache__/ p3; pytest ============================= test session starts ============================== platform linux -- Python 3.4.5, pytest-3.4.1, py-1.5.2, pluggy-0.6.0 rootdir: /home/usr/tmp/junk, inifile: collected 0 items / 1 errors ==================================== ERRORS ==================================== ______________________ ERROR collecting tests/test_ook.py ______________________ ImportError while importing test module '/home/usr/tmp/junk/tests/test_ook.py'. Hint: make sure your test modules/packages have valid Python names. Traceback: tests/test_ook.py:2: in <module> from junk.ook import add E ImportError: No module named 'junk' !!!!!!!!!!!!!!!!!!! Interrupted: 1 errors during collection !!!!!!!!!!!!!!!!!!!! =========================== 1 error in 0.08 seconds ============================ def test_add_true(): assert add(1, 1) == 2 However, running the following does work fine. p3; python -m pytest tests/ ============================= test session starts ============================== platform linux -- Python 3.4.5, pytest-3.4.1, py-1.5.2, pluggy-0.6.0 rootdir: /home/usr/tmp/junk, inifile: collected 1 item tests/test_ook.py . [100%] =========================== 1 passed in 0.02 seconds =========================== What am I doing wrong?
Update for pytest 7 and newer: use the pythonpath setting Recently, pytest has added a new core plugin that supports sys.path modifications via the pythonpath configuration value. The solution is thus much simpler now and doesn't require any workarounds anymore: pyproject.toml example: [tool.pytest.ini_options] pythonpath = [ "." ] pytest.ini example: [pytest] pythonpath = . The path entries are calculated relative to the rootdir, thus . adds junk directory to sys.path in this case. Multiple path entries are also allowed: for a layout junk/ ├── src/ | └── lib.py ├── junk/ │ ├── __init__.py │ └── ook.py └── tests ├── test_app.py └── test_lib.py the configuration [tool.pytest.ini_options] pythonpath = [ ".", "src", ] or [pytest] pythonpath = . src will add both lib module and junk package to sys.path, so import junk import lib will both work. Original answer Just put an empty conftest.py file in the project root directory: $ pwd /home/usr/tmp/junk $ touch conftest.py Your project structure should become: junk ├── conftest.py ├── junk │ ├── __init__.py │ └── ook.py └── tests └── test_ook.py What happens here: when pytest discovers a conftest.py, it modifies sys.path so it can import stuff from the conftest module. So, since now an empty conftest.py is found in rootdir, pytest will be forced to append it to sys.path. The side effect of this is that your junk module becomes importable.