Matheus
Matheus

Reputation: 209

GET error : ModuleNotFoundError: No module named 'api'

I've got an error when I try to run pytest command. The error is just when I running the application on docker, when I did it locally, it works. There's another curiosity about it, the swagger and de requests are working fine, just the test file doesn't. I have already tried :

python -m pytest tests/

pytest tests/test_api.py

docker-compose exec api pytest

I`ve got this error :

ImportError while importing test module 'C:\Users\mathe\Desktop\Teste\bluestorm-api\api\tests\test_api.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
..\..\..\..\AppData\Local\Programs\Python\Python39\lib\importlib\__init__.py:127: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
tests\test_api.py:5: in <module>
    import api.database.create_engine
E   ModuleNotFoundError: No module named 'api'

My files structure:

enter image description here

My test.py file:

from sys import api_version
from fastapi.testclient import TestClient
from sqlalchemy import text, orm
from sqlmodel import MetaData, Table
from api.main import app
from api.database import engine


client = TestClient(app) 

class TestApiGet:

    def test_login(self):
        
        
        response = app.post(
            "/login",
            data = {
            "USERNAME": "",
            "PASSWORD": ""
        })
        assert response.status_code == 200

My docker-compose file:

version: "3.8"
services:
  api:
    build: .
    command: ["uvicorn", "api.main:app", "--host=0.0.0.0", "--port=8000"]
    volumes:
      - ./api:/code/api
    ports:
      - "8000:8000"

My docker file:

FROM python:3.9-slim-buster

WORKDIR /code

# TODO: Multstage build, so the container does not runs with a compiler
RUN apt-get update && apt-get install curl build-essential unixodbc-dev wait-for-it -y

COPY ./requirements.txt .

RUN pip install -r requirements.txt

RUN apt-get remove build-essential -y

COPY ./api /code/api/

EXPOSE 8000

Upvotes: 2

Views: 4513

Answers (1)

Bastien B
Bastien B

Reputation: 1303

Your code is for the most part just fine you just have a path problem and a invalid test class.

Also it is not good practice to have your test package into your api package.

you should do something like this:

.
├── api
│   ├── __init__.py
│   ├── main.py
│   └── routers
│   │   ├── __init__.py
│   │   ├── something.py
│   │...
├── tests
│   ├── __init__.py
│   └── test_something.py
├── requirements.txt
├── Dockerfile

Also you made a syntax error with you api/__init__.py, you did put 3x _ at the biginning

your test.py file doesn't respect the norm, please check fastapi official test doc:

from fastapi.testclient import TestClient
from api.main import app

client = TestClient(app)


def test_login():
    response = client.post(
        "/login",
        data={
            "USERNAME": "",
            "PASSWORD": ""
        }
    )
    assert response.status_code == 200

in the parent folder you call:

pytest

with above structure and a simple fastapi api in main.py:

FAILED tests/test_something.py::TestApiGet::test_login - assert 404 == 200

When you have a basic test structure that is running fine, you can use test classes but here is a simpler/easier solution for the beginning.

Upvotes: 1

Related Questions