From 1af3f4549ce029ae70f145976b24885f067364f6 Mon Sep 17 00:00:00 2001 From: johnpccd Date: Sat, 24 May 2025 13:05:38 +0200 Subject: [PATCH] cp --- pytest.ini | 9 +- tests/integration/__init__.py | 1 + .../integration/test_firestore_integration.py | 166 ++++++++++++++++++ 3 files changed, 175 insertions(+), 1 deletion(-) create mode 100644 tests/integration/__init__.py create mode 100644 tests/integration/test_firestore_integration.py diff --git a/pytest.ini b/pytest.ini index 93ea8c7..c5d3c04 100644 --- a/pytest.ini +++ b/pytest.ini @@ -11,4 +11,11 @@ addopts = --strict-markers --disable-warnings markers = - asyncio: marks tests as async (deselect with '-m "not asyncio"') \ No newline at end of file + asyncio: marks tests as async (deselect with '-m "not asyncio"') + integration: marks tests as integration tests requiring real database (deselect with '-m "not integration"') + unit: marks tests as unit tests using mocks (default) + +# Integration test configuration +# To run integration tests: pytest -m integration +# To run only unit tests: pytest -m "not integration" +# To run all tests: pytest \ No newline at end of file diff --git a/tests/integration/__init__.py b/tests/integration/__init__.py new file mode 100644 index 0000000..1a80e7f --- /dev/null +++ b/tests/integration/__init__.py @@ -0,0 +1 @@ +"""Integration tests package for SEREACT database layer""" \ No newline at end of file diff --git a/tests/integration/test_firestore_integration.py b/tests/integration/test_firestore_integration.py new file mode 100644 index 0000000..96a1cfe --- /dev/null +++ b/tests/integration/test_firestore_integration.py @@ -0,0 +1,166 @@ +""" +Integration tests for Firestore database operations. + +These tests require: +1. Real Firestore credentials +2. A test Firestore database +3. Network connectivity to Google Cloud + +Run with: pytest tests/integration/ -v --integration +""" + +import pytest +import asyncio +import os +from src.db.providers.firestore_provider import FirestoreProvider +from src.db.repositories.firestore_team_repository import FirestoreTeamRepository +from src.models.team import TeamModel +from src.config.config import settings + + +@pytest.mark.integration +class TestFirestoreIntegration: + """Integration tests for real Firestore operations""" + + @pytest.fixture(scope="class") + def provider(self): + """Create a real FirestoreProvider for integration testing""" + if not os.getenv("FIRESTORE_INTEGRATION_TEST"): + pytest.skip("Integration tests disabled. Set FIRESTORE_INTEGRATION_TEST=1 to enable") + + provider = FirestoreProvider() + provider.connect() + yield provider + provider.disconnect() + + @pytest.fixture(scope="class") + def team_repository(self, provider): + """Create a real team repository for testing""" + return FirestoreTeamRepository() + + @pytest.mark.asyncio + async def test_real_firestore_connection(self, provider): + """Test actual connection to Firestore""" + assert provider.client is not None + + # Test getting a collection reference + collection = provider.get_collection("test_teams") + assert collection is not None + + @pytest.mark.asyncio + async def test_real_document_crud(self, provider): + """Test real CRUD operations on Firestore""" + collection_name = "integration_test_teams" + + # Create test data + test_data = { + "name": "Integration Test Team", + "description": "Created by integration test", + "created_at": "2024-01-01T00:00:00Z" + } + + try: + # CREATE + doc_id = await provider.add_document(collection_name, test_data) + assert doc_id is not None + + # READ + retrieved_doc = await provider.get_document(collection_name, doc_id) + assert retrieved_doc is not None + assert retrieved_doc["name"] == "Integration Test Team" + assert retrieved_doc["_id"] == doc_id + + # UPDATE + update_data = {"name": "Updated Integration Test Team"} + success = await provider.update_document(collection_name, doc_id, update_data) + assert success is True + + # Verify update + updated_doc = await provider.get_document(collection_name, doc_id) + assert updated_doc["name"] == "Updated Integration Test Team" + + # LIST + all_docs = await provider.list_documents(collection_name) + assert len(all_docs) >= 1 + assert any(doc["_id"] == doc_id for doc in all_docs) + + finally: + # CLEANUP - Delete test document + await provider.delete_document(collection_name, doc_id) + + # Verify deletion + deleted_doc = await provider.get_document(collection_name, doc_id) + assert deleted_doc is None + + @pytest.mark.asyncio + async def test_real_team_repository_operations(self, team_repository): + """Test real team repository operations""" + # Create test team + test_team = TeamModel( + name="Integration Test Team Repository", + description="Created by repository integration test" + ) + + try: + # CREATE + created_team = await team_repository.create(test_team) + assert created_team.name == test_team.name + assert hasattr(created_team, 'id') + + team_id = str(created_team.id) + + # READ + retrieved_team = await team_repository.get_by_id(team_id) + assert retrieved_team is not None + assert retrieved_team.name == test_team.name + + # UPDATE + update_data = {"description": "Updated by integration test"} + updated_team = await team_repository.update(team_id, update_data) + assert updated_team.description == "Updated by integration test" + + # LIST + all_teams = await team_repository.get_all() + assert len(all_teams) >= 1 + assert any(team.name == "Integration Test Team Repository" for team in all_teams) + + finally: + # CLEANUP + if 'team_id' in locals(): + await team_repository.delete(team_id) + + @pytest.mark.asyncio + async def test_real_error_handling(self, provider): + """Test error handling with real Firestore""" + # Test getting non-existent document + result = await provider.get_document("test_collection", "non_existent_id") + assert result is None + + # Test updating non-existent document + success = await provider.update_document("test_collection", "non_existent_id", {"test": "data"}) + assert success is True # Firestore creates the document if it doesn't exist + + # Cleanup + await provider.delete_document("test_collection", "non_existent_id") + + +# Configuration for integration tests +@pytest.fixture(scope="session", autouse=True) +def setup_integration_test_environment(): + """Setup environment for integration tests""" + if os.getenv("FIRESTORE_INTEGRATION_TEST"): + # Ensure we're using a test database + if not settings.FIRESTORE_DATABASE_NAME.endswith("-test"): + pytest.fail("Integration tests must use a test database (name should end with '-test')") + + # Ensure credentials are available + if not settings.FIRESTORE_CREDENTIALS_FILE or not os.path.exists(settings.FIRESTORE_CREDENTIALS_FILE): + pytest.fail("Integration tests require valid Firestore credentials") + + +# Pytest configuration for integration tests +def pytest_configure(config): + """Configure pytest for integration tests""" + config.addinivalue_line( + "markers", "integration: mark test as integration test (requires real database)" + ) \ No newline at end of file