diff --git a/.github/workflows/api-tests.yaml b/.github/workflows/api-tests.yaml index c8b8d1ac..c0ad6d09 100644 --- a/.github/workflows/api-tests.yaml +++ b/.github/workflows/api-tests.yaml @@ -13,14 +13,19 @@ on: jobs: test: runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v2 - - name: Setup uv - uses: astral-sh/setup-uv@v1 + steps: + - uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v4 with: - version: "latest" + python-version: "3.12" + + - name: Install uv + uses: astral-sh/setup-uv@v2 + with: + version: latest - name: Install dependencies run: | @@ -30,4 +35,13 @@ jobs: - name: Run tests run: | cd apps/api - uv run pytest -v + uv run pytest src/tests/ -v --tb=short + env: + TESTING: "true" + + - name: Run security tests with coverage + run: | + cd apps/api + uv run pytest src/tests/security/ --cov=src.security --cov-report=xml --cov-report=term-missing + env: + TESTING: "true" diff --git a/apps/api/src/core/events/database.py b/apps/api/src/core/events/database.py index 8c703c6e..b970af1a 100644 --- a/apps/api/src/core/events/database.py +++ b/apps/api/src/core/events/database.py @@ -32,24 +32,40 @@ def import_all_models(): import_all_models() learnhouse_config = get_learnhouse_config() -engine = create_engine( - learnhouse_config.database_config.sql_connection_string, # type: ignore - echo=False, - pool_pre_ping=True, # type: ignore - pool_size=5, - max_overflow=0, - pool_recycle=300, # Recycle connections after 5 minutes - pool_timeout=30 -) -# Create all tables after importing all models -SQLModel.metadata.create_all(engine) -logfire.instrument_sqlalchemy(engine=engine) +# Check if we're in test mode +is_testing = os.getenv("TESTING", "false").lower() == "true" + +if is_testing: + # Use SQLite for tests + engine = create_engine( + "sqlite:///:memory:", + echo=False, + connect_args={"check_same_thread": False} + ) +else: + # Use configured database for production/development + engine = create_engine( + learnhouse_config.database_config.sql_connection_string, # type: ignore + echo=False, + pool_pre_ping=True, # type: ignore + pool_size=5, + max_overflow=0, + pool_recycle=300, # Recycle connections after 5 minutes + pool_timeout=30 + ) + +# Only create tables if not in test mode (tests will handle this themselves) +if not is_testing: + SQLModel.metadata.create_all(engine) + logfire.instrument_sqlalchemy(engine=engine) async def connect_to_db(app: FastAPI): app.db_engine = engine # type: ignore logging.info("LearnHouse database has been started.") - SQLModel.metadata.create_all(engine) + # Only create tables if not in test mode + if not is_testing: + SQLModel.metadata.create_all(engine) def get_db_session(): with Session(engine) as session: diff --git a/apps/api/src/tests/conftest.py b/apps/api/src/tests/conftest.py index fa03eedf..853068ae 100644 --- a/apps/api/src/tests/conftest.py +++ b/apps/api/src/tests/conftest.py @@ -4,5 +4,8 @@ import os # Ensure src/ is on the Python path for all tests sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '../..'))) +# Set testing environment variable to use SQLite +os.environ["TESTING"] = "true" + # Suppress logfire warnings in tests os.environ["LOGFIRE_IGNORE_NO_CONFIG"] = "1" \ No newline at end of file