2025-05-24 13:31:31 +02:00

195 lines
5.7 KiB
Python

"""
Global test configuration and fixtures for SEREACT tests.
This file provides shared fixtures and configuration for:
- Unit tests (with mocked dependencies)
- Integration tests (with real database connections)
- End-to-end tests (with complete workflow testing)
"""
import pytest
import asyncio
import os
import tempfile
import io
from typing import Generator, Dict, Any
from fastapi.testclient import TestClient
from PIL import Image as PILImage
# Import the main app
from main import app
@pytest.fixture(scope="session")
def event_loop():
"""Create an event loop for the test session"""
loop = asyncio.new_event_loop()
yield loop
loop.close()
@pytest.fixture(scope="session")
def test_app():
"""Create the FastAPI test application"""
return app
@pytest.fixture(scope="function")
def client(test_app) -> Generator[TestClient, None, None]:
"""Create a test client for the FastAPI app"""
with TestClient(test_app) as test_client:
yield test_client
@pytest.fixture(scope="function")
def sample_image() -> io.BytesIO:
"""Create a sample image for testing uploads"""
img = PILImage.new('RGB', (100, 100), color='red')
img_bytes = io.BytesIO()
img.save(img_bytes, format='JPEG')
img_bytes.seek(0)
return img_bytes
@pytest.fixture(scope="function")
def sample_images() -> Dict[str, io.BytesIO]:
"""Create multiple sample images for testing"""
images = {}
colors = ['red', 'green', 'blue', 'yellow']
for i, color in enumerate(colors):
img = PILImage.new('RGB', (100, 100), color=color)
img_bytes = io.BytesIO()
img.save(img_bytes, format='JPEG')
img_bytes.seek(0)
images[f'{color}_image_{i}.jpg'] = img_bytes
return images
@pytest.fixture(scope="function")
def temp_image_file() -> Generator[str, None, None]:
"""Create a temporary image file for testing"""
img = PILImage.new('RGB', (200, 200), color='blue')
with tempfile.NamedTemporaryFile(suffix='.jpg', delete=False) as tmp_file:
img.save(tmp_file, format='JPEG')
tmp_file_path = tmp_file.name
yield tmp_file_path
# Cleanup
try:
os.unlink(tmp_file_path)
except OSError:
pass
@pytest.fixture(scope="function")
def test_team_data() -> Dict[str, Any]:
"""Provide test team data"""
return {
"name": "Test Team",
"description": "A team created for testing purposes"
}
@pytest.fixture(scope="function")
def test_user_data() -> Dict[str, Any]:
"""Provide test user data"""
return {
"email": "test@example.com",
"name": "Test User",
"role": "admin"
}
@pytest.fixture(scope="function")
def test_api_key_data() -> Dict[str, Any]:
"""Provide test API key data"""
return {
"name": "Test API Key",
"permissions": ["read", "write"]
}
@pytest.fixture(scope="function")
def test_image_data() -> Dict[str, Any]:
"""Provide test image metadata"""
return {
"description": "Test image for automated testing",
"tags": "test,automation,sample"
}
# Environment-specific fixtures
@pytest.fixture(scope="session")
def integration_test_enabled() -> bool:
"""Check if integration tests are enabled"""
return bool(os.getenv("FIRESTORE_INTEGRATION_TEST"))
@pytest.fixture(scope="session")
def e2e_integration_test_enabled() -> bool:
"""Check if E2E integration tests are enabled"""
return bool(os.getenv("E2E_INTEGRATION_TEST"))
# Test data cleanup utilities
@pytest.fixture(scope="function")
def cleanup_tracker():
"""Track resources created during tests for cleanup"""
resources = {
"teams": [],
"users": [],
"api_keys": [],
"images": []
}
yield resources
# Cleanup logic would go here if needed
# For now, we rely on test isolation through mocking
# Configuration for different test types
def pytest_configure(config):
"""Configure pytest with custom markers and settings"""
config.addinivalue_line(
"markers", "unit: mark test as unit test (uses mocks)"
)
config.addinivalue_line(
"markers", "integration: mark test as integration test (requires real database)"
)
config.addinivalue_line(
"markers", "e2e: mark test as end-to-end test (complete workflows)"
)
config.addinivalue_line(
"markers", "slow: mark test as slow running"
)
def pytest_collection_modifyitems(config, items):
"""Modify test collection to add markers based on test location"""
for item in items:
# Add markers based on test file location
if "integration" in str(item.fspath):
item.add_marker(pytest.mark.integration)
elif "e2e" in str(item.fspath) or item.name.startswith("test_e2e"):
item.add_marker(pytest.mark.e2e)
else:
item.add_marker(pytest.mark.unit)
# Skip conditions for different test types
def pytest_runtest_setup(item):
"""Setup conditions for running different types of tests"""
# Skip integration tests if not enabled
if item.get_closest_marker("integration"):
if not os.getenv("FIRESTORE_INTEGRATION_TEST"):
pytest.skip("Integration tests disabled. Set FIRESTORE_INTEGRATION_TEST=1 to enable")
# Skip E2E integration tests if not enabled
if item.get_closest_marker("e2e") and "integration" in item.keywords:
if not os.getenv("E2E_INTEGRATION_TEST"):
pytest.skip("E2E integration tests disabled. Set E2E_INTEGRATION_TEST=1 to enable")