Global refactoring of the project to use poetry and implement tests,

fixing bugs, changing the handling of dto and db models, preparing to
add new functionality
This commit is contained in:
2025-06-24 13:30:35 +03:00
parent 51a6ba75c0
commit 6658d773bf
58 changed files with 2521 additions and 1008 deletions

12
tests/test_authors.py Normal file
View File

@@ -0,0 +1,12 @@
import pytest
from alembic import command
from alembic.config import Config
from fastapi.testclient import TestClient
from sqlmodel import select, delete, Session
from library_service.main import app
from tests.test_misc import setup_database
client = TestClient(app)
#TODO: add tests for author endpoints

58
tests/test_books.py Normal file
View File

@@ -0,0 +1,58 @@
import pytest
from alembic import command
from alembic.config import Config
from fastapi.testclient import TestClient
from sqlmodel import select, delete, Session
from library_service.main import app
from tests.test_misc import setup_database
client = TestClient(app)
#TODO: assert descriptions
#TODO: add comments
#TODO: update tests
def test_create_book(setup_database):
response = client.post("/books", json={"title": "Test Book", "description": "Test Description"})
print(response.json())
assert response.status_code == 200
assert response.json() == {"id": 1, "title": "Test Book", "description": "Test Description"}
def test_get_existing_book(setup_database):
response = client.get("/books/1")
print(response.json())
assert response.status_code == 200
assert response.json() == {"id": 1, "title": "Test Book", "description": "Test Description", 'authors': []}
def test_get_not_existing_book(setup_database):
response = client.get("/books/2")
print(response.json())
assert response.status_code == 404
assert response.json() == {"detail": "Book not found"}
def test_update_book(setup_database):
response = client.get("/books/1")
assert response.status_code == 200
response = client.put("/books/1", json={"title": "Updated Book", "description": "Updated Description"})
assert response.status_code == 200
assert response.json() == {"id": 1, "title": "Updated Book", "description": "Updated Description"}
def test_update_not_existing_book(setup_database):
response = client.put("/books/2", json={"title": "Updated Book", "description": "Updated Description"})
assert response.status_code == 404
assert response.json() == {"detail": "Book not found"}
def test_delete_book(setup_database):
response = client.get("/books/1")
assert response.status_code == 200
response = client.delete("/books/1")
assert response.status_code == 200
assert response.json() == {"id": 1, "title": "Updated Book", "description": "Updated Description"}
def test_not_existing_delete_book(setup_database):
response = client.delete("/books/2")
assert response.status_code == 404
assert response.json() == {"detail": "Book not found"}
#TODO: add tests for other books endpoints

View File

@@ -1,70 +0,0 @@
import pytest # pyright: ignore
from fastapi.testclient import TestClient
from app.main import app
@pytest.fixture()
def client():
with TestClient(app) as test_client:
yield test_client
# Тесты для авторов
def test_create_author(client):
response = client.post("/authors/", json={"name": "Author Name"})
assert response.status_code == 200
assert response.json()["name"] == "Author Name"
def test_read_authors(client):
response = client.get("/authors/")
assert response.status_code == 200
assert isinstance(response.json(), list) # Проверяем, что ответ - это список
def test_update_author(client):
# Сначала создаем автора, чтобы его обновить
create_response = client.post("/authors/", json={"name": "Author Name"})
author_id = create_response.json()["id"]
response = client.put(f"/authors/{author_id}", json={"name": "Updated Author Name"})
assert response.status_code == 200
assert response.json()["name"] == "Updated Author Name"
def test_delete_author(client):
# Сначала создаем автора, чтобы его удалить
create_response = client.post("/authors/", json={"name": "Author Name"})
author_id = create_response.json()["id"]
author_name = create_response.json()["name"]
response = client.delete(f"/authors/{author_id}")
assert response.status_code == 200
assert response.json()["name"] == author_name
# Тесты для книг
def test_create_book(client):
response = client.post("/books/", json={"title": "Book Title", "description": "Book Description"})
assert response.status_code == 200
assert response.json()["title"] == "Book Title"
def test_read_books(client):
response = client.get("/books/")
assert response.status_code == 200
assert isinstance(response.json(), list) # Проверяем, что ответ - это список
def test_update_book(client):
# Сначала создаем книгу, чтобы ее обновить
create_response = client.post("/books/", json={"title": "Book Title", "description": "Book Description"})
book_id = create_response.json()["id"]
response = client.put(f"/books/{book_id}", json={"title": "Updated Book Title", "description": "Updated Description"})
assert response.status_code == 200
assert response.json()["title"] == "Updated Book Title"
def test_delete_book(client):
# Сначала создаем книгу, чтобы ее удалить
create_response = client.post("/books/", json={"title": "Book Title", "description": "Book Description"})
book_id = create_response.json()["id"]
book_title = create_response.json()["title"]
book_description = create_response.json()["description"]
response = client.delete(f"/books/{book_id}")
assert response.status_code == 200
assert response.json()["title"] == book_title
assert response.json()["description"] == book_description

75
tests/test_misc.py Normal file
View File

@@ -0,0 +1,75 @@
import pytest
from alembic import command
from alembic.config import Config
from fastapi.testclient import TestClient
from sqlmodel import select, delete, Session
from library_service.main import app, engine
from library_service.models.db import Author, Book, AuthorBookLink
client = TestClient(app)
@pytest.fixture(scope="module")
def setup_database():
# Save original data backup
with Session(engine) as session:
original_authors = session.exec(select(Author)).all()
original_books = session.exec(select(Book)).all()
original_links = session.exec(select(AuthorBookLink)).all()
# Reset database
alembic_cfg = Config("alembic.ini")
with engine.begin() as connection:
alembic_cfg.attributes['connection'] = connection
command.downgrade(alembic_cfg, 'base')
command.upgrade(alembic_cfg, 'head')
# Check database state after reset
with Session(engine) as session:
assert len(session.exec(select(Author)).all()) == 0
assert len(session.exec(select(Book)).all()) == 0
assert len(session.exec(select(AuthorBookLink)).all()) == 0
yield # Here pytest will start testing
# Restore original data from backup
with Session(engine) as session:
for author in original_authors:
session.add(author)
for book in original_books:
session.add(book)
for link in original_links:
session.add(link)
session.commit()
# Test the main page of the application
def test_main_page():
response = client.get("/") # Send GET request to the main page
try:
content = response.content.decode('utf-8') # Decode response content
# Find indices of key elements in the content
title_idx = content.index("Welcome to ")
description_idx = content.index("Description: ")
version_idx = content.index("Version: ")
time_idx = content.index("Current Time: ")
status_idx = content.index("Status: ")
assert response.status_code == 200, "Invalid response status"
assert content.startswith('<!doctype html>'), "Not HTML"
assert content.endswith('</html>'), "HTML tag not closed"
assert content[title_idx+1] != '<', "Title not provided"
assert content[description_idx+1] != '<', "Description not provided"
assert content[version_idx+1] != '<', "Version not provided"
assert content[time_idx+1] != '<', "Time not provided"
assert content[status_idx+1] != '<', "Status not provided"
except Exception as e:
print(f"Error: {e}") # Print error if an exception occurs
assert False, "Unexpected error" # Force test failure on unexpected error
# Test application info endpoint
def test_app_info_test():
response = client.get("/api/info") # Send GET request to the info endpoint
assert response.status_code == 200, "Invalid response status"
assert response.json()["status"] == "ok", "Status not ok"
assert response.json()["app_info"]["title"] != "", "Title not provided"
assert response.json()["app_info"]["description"] != "", "Description not provided"
assert response.json()["app_info"]["version"] != "", "Version not provided"
# Check time difference
assert 0 < (datetime.now() - datetime.fromisoformat(response.json()["server_time"])).total_seconds(), "Negative time difference"
assert (datetime.now() - datetime.fromisoformat(response.json()["server_time"])).total_seconds() < 1, "Time difference too large"

View File

@@ -0,0 +1,12 @@
import pytest
from alembic import command
from alembic.config import Config
from fastapi.testclient import TestClient
from sqlmodel import select, delete, Session
from library_service.main import app
from tests.test_misc import setup_database
client = TestClient(app)
#TODO: add tests for relationships endpoints