5

Imagine a simple folder structure:

my_folder/
    __init__.py
    funcs.py
    tests/
        test_funcs.py

funcs.py:

def f():
    return 2

__init__.py:

from funcs import f

test_funcs.py:

from funcs import f

def test_f():
    assert f() == 2

It's one of the suggested ways in the documentation: https://pytest.readthedocs.io/en/reorganize-docs/new-docs/user/directory_structure.html

But when I run pytest from my_folder:

tests/test_funcs.py:1: in <module>
    from funcs import f
E   ModuleNotFoundError: No module named 'funcs'

It's strange because I would have thought that pytest sets the path from where it's been running so those kinds of errors don't come up without dealing with it manually.

The documentation doesn't gave any indication about this either... They're just saying :

Typically you can run tests by pointing to test directories or modules:

pytest tests/test_appmodule.py      # for external test dirs
pytest src/tests/test_appmodule.py  # for inlined test dirs
pytest src                          # run tests in all below test directories
pytest                              # run all tests below current dir

What am I missing?

DevOps Craftsman
  • 355
  • 3
  • 16
  • your `__init__.py` you should have `from .funcs import f` -- you are making a package-relative import – anthony sottile Oct 11 '18 at 20:36
  • @AnthonySottile I considered that solution, as well. Unfortunately, running pytest with that modification still yields the same error: `E ModuleNotFoundError: No module named 'funcs'` – haxtar Oct 11 '18 at 20:49
  • 1
    oh also your test file should have `from my_folder.funcs import f` -- `$ python -m pytest -q my_folder` ==> `1 passed in 0.01 seconds` – anthony sottile Oct 11 '18 at 21:07
  • That works! (when it is run outside of my_folder). But running `pytest` within my_folder still fails – haxtar Oct 11 '18 at 21:19
  • This proves that the documentation is missing something! You're even providing another way to run the tests! The doc just says `pytest`... – DevOps Craftsman Oct 11 '18 at 21:57
  • At the end of the day, this has nothing to do with pytest, it's just related to how python import statements work. Always use `-m` and almost everything should be okay. – DevOps Craftsman Nov 24 '18 at 10:24
  • Possible duplicate of [PATH issue with pytest 'ImportError: No module named YadaYadaYada'](https://stackoverflow.com/questions/10253826/path-issue-with-pytest-importerror-no-module-named-yadayadayada) – DevOps Craftsman Jan 05 '19 at 15:36

2 Answers2

4

Here is a very simple way:

  1. Empty out __init__.py
  2. From a level above my_folder run python -m pytest or python -m pytest tests (but not pytest)

EXPLANATION: Running a module with the -m option will include it in the PYTHONPATH, so everything related to the import statements will be solved smoothly.

DevOps Craftsman
  • 355
  • 3
  • 16
-1

The test file test_funcs.py must be run from the directory where the module funcs is located in order for the import to be successful.

As a workaround, you can modify sys.path, which determines the interpeter's search path for modules.

test_funcs.py:

import sys
sys.path.append('/Users/Yahya/Desktop/my_folder')

from funcs import f

def test_f():
    assert f() == 2
haxtar
  • 1,962
  • 3
  • 20
  • 44
  • Just want to note: the path `"/Users/Yahya/Desktop/my_folder"` is just an example. If you would like to determine the absolute path of my_folder, you can open a terminal, `cd my_folder`, and `pwd`. – haxtar Oct 10 '18 at 20:44
  • I know about this workaround, but are you saying that the documentation is wrong, or at the very least obviously incomplete? (see the added quote) – DevOps Craftsman Oct 11 '18 at 00:52
  • 1
    monkeypatching `sys.path` is almost never the right way – anthony sottile Oct 11 '18 at 20:34
  • The only other way to be able to use `funcs` in `tests/test_funcs.py` is to move `__init__.py` (as is) from `my_folder` to `tests`. Running pytest from my_folder after this transfer will result in a passing test. Unfortunately, though, the documentation specifically advises against it: "You shouldn’t have __init__.py files in your test directories" – haxtar Oct 11 '18 at 20:44