mercredi 22 juillet 2020

How to structure local imports in main.py to allow for testing?

I am trying to test my application. I have a very standard project structured like so:

root
├── app
│   ├── __init__.py
│   ├── main.py
│   └── logic
│       └── calc.py
├── tests
│   └── test_main.py
│
└── pyproject.toml

My main.py makes use of a class from the logic/calc.py file, and looks something like this:

# app/main.py

from logic.calc import Model

def main() -> None:
    m = Model()
    print(m.some_attribute)

if __name__ == "__main__":
    main()

I can run python app/main.py and it'll work great. The problem occurs during testing:

# tests/test_main.py

from app.main import main

def test_main():
    assert main() is None

Running pytest will result in ModuleNotFoundError: No module named 'logic'. The import in main.py is going wrong!

So we can fix this by adjusting the import to from app.logic.calc import Model. The test now runs smoothly. However, now I cannot run python main.py anymore! This will result in an error: ModuleNotFoundError: No module named 'app'. So this seems like a Catch-22.

Installing the package

Installing the project as a package using pyproject.toml solves this issue, as the app module now becomes available everywhere. However, I would prefer not to install the package, as I am packaging the project in Docker, and package installation has some effects that I am trying to avoid.

Can I get both direct execution and tests working at the same time, without installing the project as a package?

It seems like a basic problem, but somehow I haven't been able to find answers or figure it out. Help much appreciated!

Aucun commentaire:

Enregistrer un commentaire