init unit tests

This commit is contained in:
grillazz 2021-03-26 13:07:42 +01:00
parent dd9096df97
commit 786bb23eab
11 changed files with 95 additions and 22 deletions

9
.env
View File

@ -1,8 +1,9 @@
PYTHONDONTWRITEBYTECODE=1 PYTHONDONTWRITEBYTECODE=1
PYTHONUNBUFFERED=1 PYTHONUNBUFFERED=1
POSTGRES_DB=devdb SQL_DB=devdb
POSTGRES_TEST_DB=testdb SQL_TEST_DB=testdb
POSTGRES_HOST=db SQL_HOST=db
POSTGRES_USER=user SQL_USER=user
SQL_PASS=secret

View File

@ -1 +0,0 @@
POSTGRES_PASS=secret

View File

@ -20,7 +20,6 @@ WORKDIR /app
COPY ./the_app/ /app/ COPY ./the_app/ /app/
COPY ./tests/ /app/ COPY ./tests/ /app/
COPY .env /app/ COPY .env /app/
COPY .secrets /app/
RUN set -ex && bash -c "eval $(grep 'PYTHONDONTWRITEBYTECODE' .env)" RUN set -ex && bash -c "eval $(grep 'PYTHONDONTWRITEBYTECODE' .env)"
RUN set -ex && bash -c "eval $(grep 'PYTHONUNBUFFERED' .env)" RUN set -ex && bash -c "eval $(grep 'PYTHONUNBUFFERED' .env)"

View File

@ -8,7 +8,7 @@ build: ## Build project with compose
.PHONY: up .PHONY: up
up: ## Run project with compose up: ## Run project with compose
docker-compose up docker-compose up --remove-orphans
.PHONY: down .PHONY: down
down: ## Reset project containers with compose down: ## Reset project containers with compose
@ -24,7 +24,7 @@ requirements: ## Refresh requirements.txt from pipfile.lock
.PHONY: test .PHONY: test
test: ## Run project tests test: ## Run project tests
docker-compose run --rm web pytest docker-compose run --rm app pytest
.PHONY: lint .PHONY: lint
lint: ## Linter project code. lint: ## Linter project code.

View File

@ -1,4 +1,4 @@
DROP DATABASE IF EXISTS devdb; DROP DATABASE IF EXISTS devdb;
CREATE DATABASE devdb; CREATE DATABASE devdb;
DROP DATABASE IF EXISTS devdb; DROP DATABASE IF EXISTS testdb;
CREATE DATABASE devdb; CREATE DATABASE testdb;

View File

@ -4,7 +4,6 @@ services:
app: app:
build: . build: .
env_file: env_file:
- .secrets
- .env - .env
command: bash -c " command: bash -c "
uvicorn the_app.main:app uvicorn the_app.main:app
@ -17,19 +16,30 @@ services:
ports: ports:
- 8080:8080 - 8080:8080
depends_on: depends_on:
- db db:
condition: service_healthy
db: db:
build: build:
context: ./db context: ./db
dockerfile: Dockerfile dockerfile: Dockerfile
volumes:
- postgres_data:/var/lib/postgresql/data
env_file: env_file:
- .secrets
- .env - .env
ports: ports:
- 5432:5432 - 5432:5432
environment: environment:
- POSTGRES_USER=${POSTGRES_USER} - POSTGRES_USER=${SQL_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASS} - POSTGRES_PASSWORD=${SQL_PASS}
- POSTGRES_DB=${POSTGRES_DB} healthcheck:
- POSTGRES_HOST_AUTH_METHOD=trust test:
[
"CMD-SHELL", "pg_isready -d $POSTGRES_DB -U $POSTGRES_USER"
]
interval: 5s
timeout: 5s
retries: 5
volumes:
postgres_data:

5
pytest.ini Normal file
View File

@ -0,0 +1,5 @@
[pytest]
python_files = tests.py test_*.py *_tests.py
addopts = --cov=.
--cov-report html:htmlcov
--cov-report term-missing

0
tests/api/__init__.py Normal file
View File

10
tests/api/test_stuff.py Normal file
View File

@ -0,0 +1,10 @@
import pytest
from fastapi import status
from httpx import AsyncClient
# decorate all tests with @pytest.mark.asyncio
pytestmark = pytest.mark.asyncio
async def test_add_stuff(client: AsyncClient):
assert True

49
tests/conftest.py Normal file
View File

@ -0,0 +1,49 @@
import pytest
from httpx import AsyncClient
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.ext.asyncio import create_async_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.exc import SQLAlchemyError
from the_app.main import app
from the_app import config
from the_app.database import get_db, engine
from the_app.models.base import Base
global_settings = config.get_settings()
url = global_settings.asyncpg_test_url
engine = create_async_engine(url)
async_session = sessionmaker(engine, expire_on_commit=False, class_=AsyncSession)
async def get_test_db():
session = async_session()
try:
yield session
await session.commit()
except SQLAlchemyError as ex:
await session.rollback()
raise ex
finally:
await session.close()
app.dependency_overrides[get_db] = get_test_db
async def start_db():
async with engine.begin() as conn:
await conn.run_sync(Base.metadata.drop_all)
await conn.run_sync(Base.metadata.create_all)
@pytest.fixture
async def client() -> AsyncClient:
async with AsyncClient(
app=app,
base_url="http://testserver",
headers={"Content-Type": "application/json"},
) as client:
await start_db()
yield client

View File

@ -26,11 +26,11 @@ class Settings(BaseSettings):
""" """
pg_user: str = os.getenv("POSTGRES_USER", "") pg_user: str = os.getenv("SQL_USER", "")
pg_pass: str = os.getenv("POSTGRES_PASS", "") pg_pass: str = os.getenv("SQL_PASS", "")
pg_host: str = os.getenv("POSTGRES_HOST", "") pg_host: str = os.getenv("SQL_HOST", "")
pg_database: str = os.getenv("POSTGRES_DB", "") pg_database: str = os.getenv("SQL_DB", "")
pg_test_database: str = os.getenv("POSTGRES_TEST_DB", "") pg_test_database: str = os.getenv("SQL_TEST_DB", "")
asyncpg_url: str = f"postgresql+asyncpg://{pg_user}:{pg_pass}@{pg_host}:5432/{pg_database}" asyncpg_url: str = f"postgresql+asyncpg://{pg_user}:{pg_pass}@{pg_host}:5432/{pg_database}"
asyncpg_test_url: str = f"postgresql+asyncpg://{pg_user}:{pg_pass}@{pg_host}:5432/{pg_test_database}" asyncpg_test_url: str = f"postgresql+asyncpg://{pg_user}:{pg_pass}@{pg_host}:5432/{pg_test_database}"