2

I have the following directory structure with my python project.

Project root
├── src
│   ├── __init__.py
│   ├── app.py
│   ├── lib
│   │   ├── __init__.py
│   │   ├── libA.py
│   │   └── libB.py
└── tests
    ├── __init__.py
    └── test_app.py

app.py has from lib.libA import LibA statement.

test_app.py has the import statement from src.app import App,

When I run pytest, I can make test_app.py to import by adding __init__.py to src folder, but when app.py is importing from lib.libA import LibA, it fails in pytest.

ImportError while importing test module '/projectroot/tests/test_app.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
import_module
    return _bootstrap._gcd_import(name[level:], package, level)
tests/test_app.py:6: in <module>
    from src.app import App
src/lib/libA.py:5: in <module>
    from lib.libB import LibB
E   ModuleNotFoundError: No module named 'lib'

So the import chain is something like tests/test_app.py -> src/app.py -> src/lib/libA.py -> src/lib/libB.py. App needs to import libA, and libA imports libB.

One way I can fix is by doing sys.path.append("src/") to tests/__init__.py, but it does not look like a standard way to me.

Is there any correct/better way to fix this issue?

Edit: I would like to understand if my directory structure is incorrect, or am I importing the wrong way. I understand I could use tricks like sys.path.append() or modify PYTHONPATH, but I am looking for a "better" way.

thuyein
  • 1,684
  • 13
  • 29
  • 1
    Does this answer your question? [PATH issue with pytest 'ImportError: No module named YadaYadaYada'](https://stackoverflow.com/questions/10253826/path-issue-with-pytest-importerror-no-module-named-yadayadayada) – MrBean Bremen Apr 29 '21 at 10:42
  • @MrBeanBremen Thanks for your comment, but no. I am aware of the answer stated in that question, which I listed in mine as one solution that I can fix. I would like to know if my structure is incorrect, or am I importing the wrong way. – thuyein Apr 29 '21 at 12:44
  • You have seen that there is more than one answer to that question, right? – MrBean Bremen Apr 29 '21 at 14:50
  • You are not using the imports right. First, the `src` directory is usually used to hide the code from the interpreter, so you are forced to install your project in order to test it. Now, you are using `src` as a package (by putting an `__init__.py` into it), so either `from src.lib.libB import LibB` (absolute), or `from .lib.libB import LibB` (relative). – hoefling Apr 29 '21 at 22:13
  • So the correct way is to install the project and run the tests on the installed version? My project needs to install to `/opt/companyname/projectname`, in this case I would still need to do `sys.path.append` right? – thuyein Apr 30 '21 at 01:54

0 Answers0