Skip to content

Commit 8c58aac

Browse files
committed
setup test client for database and without database with test coverage 100% for frontend routes
1 parent 44446bb commit 8c58aac

File tree

2 files changed

+138
-0
lines changed

2 files changed

+138
-0
lines changed

tests/conftest.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import pytest
2+
from fastapi.testclient import TestClient
3+
from sqlalchemy import create_engine
4+
from sqlalchemy.orm import sessionmaker
5+
from sqlalchemy.pool import StaticPool
6+
7+
from fastapi_app import create_app
8+
from fastapi_app.postgres_models import Base
9+
10+
POSTGRESQL_DATABASE_URL = "postgresql://admin:postgres@localhost:5432/postgres"
11+
12+
13+
# Create a SQLAlchemy engine
14+
engine = create_engine(
15+
POSTGRESQL_DATABASE_URL,
16+
poolclass=StaticPool,
17+
)
18+
19+
# Create a sessionmaker to manage sessions
20+
TestingSessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
21+
22+
23+
@pytest.fixture(scope="session")
24+
def setup_database():
25+
"""Create tables in the database for all tests."""
26+
try:
27+
Base.metadata.create_all(bind=engine)
28+
yield
29+
Base.metadata.drop_all(bind=engine)
30+
except Exception as e:
31+
pytest.skip(f"Unable to connect to the database: {e}")
32+
33+
34+
@pytest.fixture(scope="function")
35+
def db_session(setup_database):
36+
"""Create a new database session with a rollback at the end of the test."""
37+
connection = engine.connect()
38+
transaction = connection.begin()
39+
session = TestingSessionLocal(bind=connection)
40+
yield session
41+
session.close()
42+
transaction.rollback()
43+
connection.close()
44+
45+
46+
@pytest.fixture(scope="function")
47+
def test_db_client(db_session):
48+
"""Create a test client that uses the override_get_db fixture to return a session."""
49+
50+
def override_db_session():
51+
try:
52+
yield db_session
53+
finally:
54+
db_session.close()
55+
56+
app = create_app()
57+
app.router.lifespan = override_db_session
58+
with TestClient(app) as test_client:
59+
yield test_client
60+
61+
62+
@pytest.fixture(scope="function")
63+
def test_client():
64+
"""Create a test client."""
65+
app = create_app()
66+
with TestClient(app) as test_client:
67+
yield test_client

tests/test_endpoints.py

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import os
2+
3+
import pytest
4+
5+
6+
@pytest.mark.asyncio
7+
async def test_index(test_client):
8+
"""test the index route"""
9+
response = test_client.get("/")
10+
11+
html_index_file_path = "src/static/index.html"
12+
with open(html_index_file_path, "rb") as f:
13+
html_index_file = f.read()
14+
15+
assert response.status_code == 200
16+
assert response.headers["Content-Type"] == "text/html; charset=utf-8"
17+
assert response.headers["Content-Length"] == str(len(html_index_file))
18+
assert html_index_file == response.content
19+
20+
21+
@pytest.mark.asyncio
22+
async def test_favicon(test_client):
23+
"""test the favicon route"""
24+
response = test_client.get("/favicon.ico")
25+
26+
favicon_file_path = "src/static/favicon.ico"
27+
with open(favicon_file_path, "rb") as f:
28+
favicon_file = f.read()
29+
30+
assert response.status_code == 200
31+
assert response.headers["Content-Type"] == "image/vnd.microsoft.icon"
32+
assert response.headers["Content-Length"] == str(len(favicon_file))
33+
assert favicon_file == response.content
34+
35+
36+
@pytest.mark.asyncio
37+
async def test_assets_non_existent_404(test_client):
38+
"""test the assets route with a non-existent file"""
39+
response = test_client.get("/assets/manifest.json")
40+
41+
assert response.status_code == 404
42+
assert response.headers["Content-Type"] == "application/json"
43+
assert response.headers["Content-Length"] == "22"
44+
assert b'{"detail":"Not Found"}' in response.content
45+
46+
47+
@pytest.mark.asyncio
48+
async def test_assets(test_client):
49+
"""test the assets route with an existing file"""
50+
assets_dir_path = "src/static/assets"
51+
assets_file_path = os.listdir(assets_dir_path)[0]
52+
53+
with open(os.path.join(assets_dir_path, assets_file_path), "rb") as f:
54+
assets_file = f.read()
55+
56+
response = test_client.get(f"/assets/{assets_file_path}")
57+
58+
assert response.status_code == 200
59+
assert response.headers["Content-Length"] == str(len(assets_file))
60+
assert assets_file == response.content
61+
62+
63+
@pytest.mark.asyncio
64+
async def test_chat_non_json_415(test_client):
65+
"""test the chat route with a non-json request"""
66+
response = test_client.post("/chat")
67+
68+
assert response.status_code == 422
69+
assert response.headers["Content-Type"] == "application/json"
70+
assert response.headers["Content-Length"] == "82"
71+
assert b'{"detail":[{"type":"missing"' in response.content

0 commit comments

Comments
 (0)