194 lines
5.6 KiB
Python
194 lines
5.6 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",
|
|
}
|
|
|
|
|
|
# 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") |