Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
8672990
added api_test.py
Apr 9, 2025
4ffa2af
added conftest.py
Apr 9, 2025
7e0937c
solved pylint issue of api_test.py
Apr 9, 2025
98e122f
feat: added unit test cases for cosmosdb_test.py file
Prashant-Microsoft Apr 11, 2025
3e090de
feat: added unit test cases for config.py, database_base.py, database…
VishalS-Microsoft Apr 11, 2025
d25c583
Merge branch 'psl-backend-unit-test' of https://github.com/microsoft/…
VishalS-Microsoft Apr 11, 2025
fdc6481
updated batch_service_test.py
Apr 15, 2025
1bfbef0
added app_test file
Apr 22, 2025
dfe155e
editing test workflow
Apr 22, 2025
e6ff115
Merge remote-tracking branch 'origin/hotfix' into psl-backend-unit-test
Prashant-Microsoft Apr 22, 2025
4a51e3b
Merge branch 'psl-backend-unit-test' of https://github.com/microsoft/…
Prashant-Microsoft Apr 22, 2025
ad088a2
updated batch-service-test
Apr 22, 2025
3869570
Merge branch 'psl-backend-unit-test' of https://github.com/microsoft/…
Apr 22, 2025
70a1ec2
added AzureAIAgent path
Kanchan-Microsoft Apr 23, 2025
132d029
Merge branch 'psl-backend-unit-test' of https://github.com/microsoft/…
Kanchan-Microsoft Apr 23, 2025
9ed8584
edit
Kanchan-Microsoft Apr 23, 2025
61517c0
added agent_config file
Apr 23, 2025
9dd8526
updated import path
Apr 23, 2025
85cfeea
edit2
Apr 23, 2025
ba5a529
edit workflow
Apr 23, 2025
7085a79
edited file path
Apr 24, 2025
fa9dfe8
app_logger
Kanchan-Microsoft Apr 24, 2025
d94f66e
edit
Kanchan-Microsoft Apr 24, 2025
be46496
Pylint issue fix
VishalS-Microsoft Apr 24, 2025
89fed7a
fixed app_logger.py test cases and pylint issue.
VishalS-Microsoft Apr 24, 2025
06eca57
feat: updated unit test cases for cosmosdb_test file
Prashant-Microsoft Apr 24, 2025
204deae
fix: pylint issues of cosmosdb_test file
Prashant-Microsoft Apr 24, 2025
cd098d4
feat: added pytest-mock package
Prashant-Microsoft Apr 24, 2025
1003610
fixed blob_base.py and blob_factory.py file test cases
VishalS-Microsoft Apr 24, 2025
4cedd0f
removed psl-backend-unit-test line
VishalS-Microsoft Apr 24, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ jobs:
- name: Run Backend Tests with Coverage
if: env.skip_backend_tests == 'false'
run: |
cd src/tests/backend
cd src
pytest --cov=. --cov-report=term-missing --cov-report=xml


Expand Down
69 changes: 35 additions & 34 deletions src/backend/common/database/database_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,55 +16,55 @@ class DatabaseBase(ABC):

@abstractmethod
async def initialize_cosmos(self) -> None:
"""Initialize the cosmosdb client and create container if needed."""
pass
"""Initialize the cosmosdb client and create container if needed"""
pass # pragma: no cover

@abstractmethod
async def create_batch(self, user_id: str, batch_id: uuid.UUID) -> BatchRecord:
"""Create a new conversion batch."""
pass
"""Create a new conversion batch"""
pass # pragma: no cover

@abstractmethod
async def get_file_logs(self, file_id: str) -> Dict:
"""Retrieve all logs for a file."""
pass
"""Retrieve all logs for a file"""
pass # pragma: no cover

@abstractmethod
async def get_batch_from_id(self, batch_id: str) -> Dict:
"""Retrieve all logs for a file."""
pass
"""Retrieve all logs for a file"""
pass # pragma: no cover

@abstractmethod
async def get_batch_files(self, batch_id: str) -> List[Dict]:
"""Retrieve all files for a batch."""
pass
"""Retrieve all files for a batch"""
pass # pragma: no cover

@abstractmethod
async def delete_file_logs(self, file_id: str) -> None:
"""Delete all logs for a file."""
pass
"""Delete all logs for a file"""
pass # pragma: no cover

@abstractmethod
async def get_user_batches(self, user_id: str) -> Dict:
"""Retrieve all batches for a user."""
pass
"""Retrieve all batches for a user"""
pass # pragma: no cover

@abstractmethod
async def add_file(
self, batch_id: uuid.UUID, file_id: uuid.UUID, file_name: str, storage_path: str
) -> FileRecord:
"""Add a file entry to the database."""
pass
"""Add a file entry to the database"""
pass # pragma: no cover

@abstractmethod
async def get_batch(self, user_id: str, batch_id: str) -> Optional[Dict]:
"""Retrieve a batch and its associated files."""
pass
"""Retrieve a batch and its associated files"""
pass # pragma: no cover

@abstractmethod
async def get_file(self, file_id: str) -> Optional[Dict]:
"""Retrieve a file entry along with its logs."""
pass
"""Retrieve a file entry along with its logs"""
pass # pragma: no cover

@abstractmethod
async def add_file_log(
Expand All @@ -76,39 +76,40 @@ async def add_file_log(
agent_type: AgentType,
author_role: AuthorRole,
) -> None:
"""Log a file status update."""
pass
"""Log a file status update"""
pass # pragma: no cover

@abstractmethod
async def update_file(self, file_record: FileRecord) -> None:
"""Update file record."""
pass
"""Update file record"""
pass # pragma: no cover

@abstractmethod
async def update_batch(self, batch_record: BatchRecord) -> BatchRecord:
"""Update a batch record"""
pass # pragma: no cover

@abstractmethod
async def delete_all(self, user_id: str) -> None:
"""Delete all batches, files, and logs for a user."""
pass
"""Delete all batches, files, and logs for a user"""
pass # pragma: no cover

@abstractmethod
async def delete_batch(self, user_id: str, batch_id: str) -> None:
"""Delete a batch along with its files and logs."""
pass
"""Delete a batch along with its files and logs"""
pass # pragma: no cover

@abstractmethod
async def delete_file(self, user_id: str, batch_id: str, file_id: str) -> None:
"""Delete a file and its logs, and update batch file count."""
pass
"""Delete a file and its logs, and update batch file count"""
pass # pragma: no cover

@abstractmethod
async def get_batch_history(self, user_id: str, batch_id: str) -> List[Dict]:
"""Retrieve all logs for a batch."""
pass
"""Retrieve all logs for a batch"""
pass # pragma: no cover

@abstractmethod
async def close(self) -> None:
"""Close database connection."""
pass
"""Close database connection"""
pass # pragma: no cover
36 changes: 16 additions & 20 deletions src/backend/common/database/database_factory.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import asyncio
from typing import Optional

from common.config.config import Config
Expand Down Expand Up @@ -33,25 +34,20 @@ async def get_database():
# Note that you have to assign yourself data plane access to Cosmos in script for this to work locally. See
# https://learn.microsoft.com/en-us/azure/cosmos-db/table/security/how-to-grant-data-plane-role-based-access?tabs=built-in-definition%2Ccsharp&pivots=azure-interface-cli
# Note that your principal id is your entra object id for your user account.
if __name__ == "__main__":
# Example usage
import asyncio

async def main():
database = await DatabaseFactory.get_database()
# Use the database instance...
await database.initialize_cosmos()
await database.create_batch("mark1", "123e4567-e89b-12d3-a456-426614174000")
await database.add_file(
"123e4567-e89b-12d3-a456-426614174000",
"123e4567-e89b-12d3-a456-426614174001",
"q1_informix.sql",
"https://cmsamarktaylstor.blob.core.windows.net/cmsablob",
)
tstbatch = await database.get_batch(
"mark1", "123e4567-e89b-12d3-a456-426614174000"
)
print(tstbatch)
await database.close()
async def main():
database = await DatabaseFactory.get_database()
await database.initialize_cosmos()
await database.create_batch("mark1", "123e4567-e89b-12d3-a456-426614174000")
await database.add_file(
"123e4567-e89b-12d3-a456-426614174000",
"123e4567-e89b-12d3-a456-426614174001",
"q1_informix.sql",
"https://cmsamarktaylstor.blob.core.windows.net/cmsablob",
)
tstbatch = await database.get_batch("mark1", "123e4567-e89b-12d3-a456-426614174000")
print(tstbatch)
await database.close()


if __name__ == "__main__":
asyncio.run(main())
18 changes: 9 additions & 9 deletions src/backend/common/storage/blob_factory.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import asyncio
from typing import Optional

from common.config.config import Config # Load config
Expand Down Expand Up @@ -31,15 +32,14 @@ async def close_storage() -> None:


# Local testing of config and code
if __name__ == "__main__":
# Example usage
import asyncio
async def main():
storage = await BlobStorageFactory.get_storage()

# Use the storage instance
blob = await storage.get_file("q1_informix.sql")
print("Blob content:", blob)

async def main():
storage = await BlobStorageFactory.get_storage()
# Use the storage instance...
blob = await storage.get_file("q1_informix.sql")
print(blob)
await BlobStorageFactory.close_storage()
await BlobStorageFactory.close_storage()

if __name__ == "__main__":
asyncio.run(main())
1 change: 1 addition & 0 deletions src/backend/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ azure-functions

# Development tools
pytest
pytest-mock
black
pylint
flake8
Expand Down
2 changes: 1 addition & 1 deletion src/backend/sql_agents/helpers/agents_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import logging

from semantic_kernel.agents import AzureAIAgent # pylint: disable=E0611
from semantic_kernel.agents.azure_ai.azure_ai_agent import AzureAIAgent # pylint: disable=E0611

from sql_agents.agents.agent_config import AgentBaseConfig
from sql_agents.agents.fixer.setup import setup_fixer_agent
Expand Down
3 changes: 1 addition & 2 deletions src/backend/sql_agents/process_batch.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,10 @@
from fastapi import HTTPException


from semantic_kernel.agents import AzureAIAgent # pylint: disable=E0611
from semantic_kernel.agents.azure_ai.azure_ai_agent import AzureAIAgent # pylint: disable=E0611
from semantic_kernel.contents import AuthorRole
from semantic_kernel.exceptions.service_exceptions import ServiceResponseException


from sql_agents.agents.agent_config import AgentBaseConfig
from sql_agents.convert_script import convert_script
from sql_agents.helpers.agents_manager import SqlAgents
Expand Down
33 changes: 33 additions & 0 deletions src/tests/backend/app_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from backend.app import create_app

from fastapi import FastAPI

from httpx import ASGITransport
from httpx import AsyncClient

import pytest


@pytest.fixture
def app() -> FastAPI:
"""Fixture to create a test app instance."""
return create_app()


@pytest.mark.asyncio
async def test_health_check(app: FastAPI):
"""Test the /health endpoint returns a healthy status."""
transport = ASGITransport(app=app)
async with AsyncClient(transport=transport, base_url="http://test") as ac:
response = await ac.get("/health")
assert response.status_code == 200
assert response.json() == {"status": "healthy"}


@pytest.mark.asyncio
async def test_backend_routes_exist(app: FastAPI):
"""Ensure /api routes are available (smoke test)."""
# Check available routes include /api prefix from backend_router
routes = [route.path for route in app.router.routes]
backend_routes = [r for r in routes if r.startswith("/api")]
assert backend_routes, "No backend routes found under /api prefix"
Loading