11import pytest
2+ import os
23from typing import Generator
34from sqlmodel import create_engine , Session , select
45from sqlalchemy import Engine
56from fastapi .testclient import TestClient
67from dotenv import load_dotenv
7- from utils .core .db import get_connection_url , tear_down_db , set_up_db , create_default_roles
8+ from utils .core .db import get_connection_url , tear_down_db , set_up_db , create_default_roles , ensure_database_exists
89from utils .core .models import User , PasswordResetToken , EmailUpdateToken , Organization , Role , Account , Invitation
910from utils .core .auth import get_password_hash , create_access_token , create_refresh_token
1011from main import app
1112from datetime import datetime , UTC , timedelta
1213
13- # Load environment variables
14- load_dotenv (override = True )
15-
1614# Define a custom exception for test setup errors
1715class SetupError (Exception ):
1816 """Exception raised for errors in the test setup process."""
@@ -21,29 +19,44 @@ def __init__(self, message="An error occurred during test setup"):
2119 super ().__init__ (self .message )
2220
2321
24- @pytest .fixture (scope = "session" )
25- def engine () -> Engine :
22+ @pytest .fixture
23+ def env_vars (monkeypatch ):
24+ # Get valid db user, password, host, and port from .env
25+ load_dotenv ()
26+ os .environ ["DB_HOST" ] = os .getenv ("DB_HOST" , "localhost" )
27+ os .environ ["DB_PORT" ] = os .getenv ("DB_PORT" , "5432" )
28+ os .environ ["DB_USER" ] = os .getenv ("DB_USER" , "appuser" )
29+ os .environ ["DB_PASSWORD" ] = os .getenv ("DB_PASSWORD" , "testpassword" )
30+
31+ # monkeypatch remaining env vars
32+ with monkeypatch .context () as m :
33+ m .setenv ("SECRET_KEY" , "testsecretkey" )
34+ m .setenv ("HOST_NAME" , "Test Organization" )
35+ m .setenv ("DB_HOST" , os .getenv ("DB_HOST" , "localhost" ))
36+ m .setenv ("DB_PORT" , os .getenv ("DB_PORT" , "5432" ))
37+ m .setenv ("DB_USER" , os .getenv ("DB_USER" , "appuser" ))
38+ m .setenv ("DB_PASSWORD" , os .getenv ("DB_PASSWORD" , "testpassword" ))
39+ m .setenv ("DB_NAME" , "qual2db4-test-db" )
40+ m .setenv ("RESEND_API_KEY" , "test" )
41+ m .setenv ("EMAIL_FROM" , "test@example.com" )
42+ m .setenv ("QUALTRICS_BASE_URL" , "test" )
43+ m .setenv ("QUALTRICS_API_TOKEN" , "test" )
44+ yield
45+
46+
47+ @pytest .fixture
48+ def engine (env_vars ) -> Engine :
2649 """
2750 Create a new SQLModel engine for the test database.
2851 Use PostgreSQL for testing to match production environment.
2952 """
3053 # Use PostgreSQL for testing to match production environment
54+ ensure_database_exists (get_connection_url ())
3155 engine = create_engine (get_connection_url ())
32- return engine
56+ set_up_db ( drop = True )
3357
58+ yield engine
3459
35- @pytest .fixture (scope = "session" , autouse = True )
36- def set_up_database (engine ) -> Generator [None , None , None ]:
37- """
38- Set up the test database before running the test suite.
39- Drop all tables and recreate them to ensure a clean state.
40- """
41- # Drop and recreate all tables using the helpers from db.py
42- tear_down_db ()
43- set_up_db (drop = False )
44-
45- yield
46-
4760 # Clean up after tests
4861 tear_down_db ()
4962
@@ -57,20 +70,7 @@ def session(engine) -> Generator[Session, None, None]:
5770 yield session
5871
5972
60- @pytest .fixture (autouse = True )
61- def clean_db (session : Session ) -> None :
62- """
63- Cleans up the database tables before each test.
64- """
65- # Don't delete permissions as they are required for tests
66- for model in (PasswordResetToken , EmailUpdateToken , User , Role , Organization , Account ):
67- for record in session .exec (select (model )).all ():
68- session .delete (record )
69-
70- session .commit ()
71-
72-
73- @pytest .fixture ()
73+ @pytest .fixture
7474def test_account (session : Session ) -> Account :
7575 """
7676 Creates a test account in the database.
@@ -85,7 +85,7 @@ def test_account(session: Session) -> Account:
8585 return account
8686
8787
88- @pytest .fixture ()
88+ @pytest .fixture
8989def test_user (session : Session , test_account : Account ) -> User :
9090 """
9191 Creates a test user in the database linked to the test account.
@@ -103,7 +103,7 @@ def test_user(session: Session, test_account: Account) -> User:
103103 return user
104104
105105
106- @pytest .fixture ()
106+ @pytest .fixture
107107def unauth_client (session : Session ) -> Generator [TestClient , None , None ]:
108108 """
109109 Provides a TestClient instance without authentication.
@@ -112,7 +112,7 @@ def unauth_client(session: Session) -> Generator[TestClient, None, None]:
112112 yield client
113113
114114
115- @pytest .fixture ()
115+ @pytest .fixture
116116def auth_client (session : Session , test_account : Account , test_user : User ) -> Generator [TestClient , None , None ]:
117117 """
118118 Provides a TestClient instance with valid authentication tokens.
0 commit comments