2

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
JustAG33K
  • 1,403
  • 3
  • 13
  • 28
Matheus
  • 139
  • 4
  • 13
  • Please post your dockerfile and docker-compose file. This may help shed some light. – Paul Stoner Aug 04 '22 at 22:01
  • Does this answer your question? [ModuleNotFoundError: No module named 'api'](https://stackoverflow.com/questions/44925635/modulenotfounderror-no-module-named-api) – hlin03 Aug 04 '22 at 22:33
  • I've added the docker and docker-compose files. – Matheus Aug 04 '22 at 22:34
  • @Henry03, the solution for this question is already implemented on my case, but the problem persist. – Matheus Aug 04 '22 at 22:35
  • Run pytest from the parent folder of `api` for it to be considered a module. – aaron Aug 07 '22 at 00:53
  • Please have a look [here](https://stackoverflow.com/questions/71079874/python-modulenotfounderror-while-importing-a-module-in-conftest-for-pytest-frame/71080756#71080756), [here](https://stackoverflow.com/q/71311507/17865804), as well as [here](https://stackoverflow.com/q/67712314/17865804) and [here](https://stackoverflow.com/q/73206540/17865804). – Chris Aug 07 '22 at 05:43
  • So `from api.main import app` works, but not the subsequent `from api.database import engine`? What happens in `main.py`? Why does the error state about importing `create_engine`, but `engine` is imported in the sample test module? Please add a [mcve] and not just half-baked snippets if you want help and not just general advices. – hoefling Aug 07 '22 at 10:29

1 Answers1

1

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.

Bastien B
  • 1,018
  • 8
  • 25