1

When I run pytest in my fastapi barebones app I get the error below. My test is in a file test_rms.py inside a tests folder. and I'm importing app from a main.py outside the tests folder. My file structure is also below. Why am I getting this error? Do I have to qualify my "from main import app" somehow? Thanks.

Contents of test_rms.py

from fastapi.testclient import TestClient
from main import app

client = TestClient(app)

def test_root():
    response = client.get("/test")
    assert response.status_code == 200
    assert response.json() == {"message": "Hello World"}

Folder Structure:

enter image description here

ERROR:

___________________________________________________________________________________________________________________________________ ERROR collecting tests/test_rms.py ___________________________________________________________________________________________________________________________________ 
    ImportError while importing test module 'C:\Scripting\Python\cct-api\tests\test_rms.py'.
    Hint: make sure your test modules/packages have valid Python names.
    Traceback:
    C:\Users\azadmin\AppData\Local\Programs\Python\Python311\Lib\importlib\__init__.py:126: in import_module
        return _bootstrap._gcd_import(name[level:], package, level)
    tests\test_rms.py:2: in <module>
        from main import app
    E   ModuleNotFoundError: No module named 'main'
configure.ng
  • 159
  • 1
  • 11
  • 1
    See this article on relative imports, from files in a different directory: https://realpython.com/absolute-vs-relative-python-imports/#relative-imports – Adam Smooch May 11 '23 at 18:12

1 Answers1

0

Your root directory is not a python package (it has no __init__.py file). I suggest modifying you project to look like this:

project/
  cctapi/
    endpoints/
      __init__.py
      rms_endpoints.py
    __init__.py
    main.py
  tests/
    test_rms.py
  .gitignore
  ...

Then you should be able to write:

from cctapi.main import app

If you still want a main.py file in the root of your project directory, you can make it reference the one which is packaged. I try to make these types of files as minimal as possible, such that the bulk of my logic is contained in my packages.

import uvicorn

from cctapi.main import app


if __name__ == "__main__":
    uvicorn.run(app, host="127.0.0.1", port=8080)

Once you get further with your packaging, you can perform this type of action by setting up configurations in your pyproject.toml. See Specifying command line scripts in pyproject.toml

If you are not running the tests from the root of the project directory, make sure to add the project root to your PYTHONPATH environment variable.

export PYTHONPATH=/path/to/my/project:$PYTHONPATH
flakes
  • 21,558
  • 8
  • 41
  • 88
  • Thanks for the advice. I switched the structure to the one you recommended but now I'm getting "from cctapi.main import app E ModuleNotFoundError: No module named 'cctapi'" when running pytest. I believe I'm running the tests from the root so I shouldn't have to add the project root to pythonpath. – configure.ng May 11 '23 at 19:19
  • @configure.ng do you get the same error running `python -c 'from cctapi.main import app'` on the command line ? And did you put the empty `__init__.py` files in there? – flakes May 11 '23 at 23:20