64ce279a2e
- Testing strategy document - Unit tests for GPS validator - Integration test conftest with fixtures - Sample .sub files and manifests - Comprehensive Termux testing guide - Test directory structure
188 lines
4.7 KiB
Python
188 lines
4.7 KiB
Python
"""
|
|
Pytest Configuration and Shared Fixtures
|
|
|
|
Provides shared test fixtures for unit and integration tests
|
|
"""
|
|
|
|
import pytest
|
|
import tempfile
|
|
import shutil
|
|
from pathlib import Path
|
|
from sqlalchemy import create_engine
|
|
from sqlalchemy.orm import sessionmaker
|
|
from fastapi.testclient import TestClient
|
|
|
|
from src.database.models import Base
|
|
from src.core.storage import LocalStorage
|
|
from config.settings import settings
|
|
|
|
|
|
# =============================================================================
|
|
# DATABASE FIXTURES
|
|
# =============================================================================
|
|
|
|
@pytest.fixture(scope="session")
|
|
def test_db_engine():
|
|
"""
|
|
Create test database engine
|
|
|
|
Uses in-memory SQLite for fast tests
|
|
"""
|
|
# Use SQLite in-memory for tests
|
|
engine = create_engine("sqlite:///:memory:", echo=False)
|
|
|
|
# Create all tables
|
|
Base.metadata.create_all(engine)
|
|
|
|
yield engine
|
|
|
|
# Cleanup
|
|
Base.metadata.drop_all(engine)
|
|
engine.dispose()
|
|
|
|
|
|
@pytest.fixture
|
|
def db_session(test_db_engine):
|
|
"""
|
|
Database session fixture
|
|
|
|
Creates a new session for each test and rolls back after
|
|
"""
|
|
Session = sessionmaker(bind=test_db_engine)
|
|
session = Session()
|
|
|
|
yield session
|
|
|
|
session.rollback()
|
|
session.close()
|
|
|
|
|
|
# =============================================================================
|
|
# STORAGE FIXTURES
|
|
# =============================================================================
|
|
|
|
@pytest.fixture
|
|
def temp_storage_dir():
|
|
"""
|
|
Temporary storage directory
|
|
|
|
Creates a temp dir and cleans up after test
|
|
"""
|
|
temp_dir = tempfile.mkdtemp(prefix="giglez_test_")
|
|
|
|
yield Path(temp_dir)
|
|
|
|
# Cleanup
|
|
shutil.rmtree(temp_dir, ignore_errors=True)
|
|
|
|
|
|
@pytest.fixture
|
|
def test_storage(temp_storage_dir):
|
|
"""
|
|
Test storage backend (LocalStorage)
|
|
|
|
Uses temporary directory
|
|
"""
|
|
return LocalStorage(base_path=str(temp_storage_dir))
|
|
|
|
|
|
# =============================================================================
|
|
# API FIXTURES
|
|
# =============================================================================
|
|
|
|
@pytest.fixture
|
|
def test_client():
|
|
"""
|
|
FastAPI test client
|
|
|
|
Provides TestClient for API endpoint testing
|
|
"""
|
|
from src.api.main import app
|
|
|
|
client = TestClient(app)
|
|
return client
|
|
|
|
|
|
# =============================================================================
|
|
# SAMPLE DATA FIXTURES
|
|
# =============================================================================
|
|
|
|
@pytest.fixture
|
|
def sample_sub_file_key():
|
|
"""Sample .sub file content (KEY format)"""
|
|
return """Filetype: Flipper SubGhz Key File
|
|
Version: 1
|
|
Frequency: 433920000
|
|
Preset: FuriHalSubGhzPresetOok270Async
|
|
Protocol: Princeton
|
|
Bit: 24
|
|
Key: 00 00 00 00 00 95 D5 D4
|
|
TE: 400
|
|
"""
|
|
|
|
|
|
@pytest.fixture
|
|
def sample_sub_file_raw():
|
|
"""Sample .sub file content (RAW format)"""
|
|
return """Filetype: Flipper SubGhz RAW File
|
|
Version: 1
|
|
Frequency: 315000000
|
|
Preset: FuriHalSubGhzPresetOok650Async
|
|
Protocol: RAW
|
|
RAW_Data: 2980 -240 520 -980 520 -980 1000 -500 480 -1020
|
|
"""
|
|
|
|
|
|
@pytest.fixture
|
|
def sample_manifest():
|
|
"""Sample upload manifest"""
|
|
return {
|
|
"session_uuid": "test-session-001",
|
|
"captures": [
|
|
{
|
|
"filename": "test.sub",
|
|
"latitude": 40.7128,
|
|
"longitude": -74.0060,
|
|
"accuracy": 5.0,
|
|
"altitude": 10.5,
|
|
"timestamp": "2026-01-12T10:00:00Z"
|
|
}
|
|
]
|
|
}
|
|
|
|
|
|
@pytest.fixture
|
|
def sample_gps_coordinates():
|
|
"""Sample GPS coordinates (valid)"""
|
|
return [
|
|
(40.7128, -74.0060, 5.0, "NYC"),
|
|
(51.5074, -0.1278, 8.0, "London"),
|
|
(35.6762, 139.6503, 3.0, "Tokyo"),
|
|
(-33.8688, 151.2093, 10.0, "Sydney"),
|
|
]
|
|
|
|
|
|
@pytest.fixture
|
|
def invalid_gps_coordinates():
|
|
"""Invalid GPS coordinates for testing"""
|
|
return [
|
|
(91.0, 0.0, 5.0, "Latitude > 90"),
|
|
(-91.0, 0.0, 5.0, "Latitude < -90"),
|
|
(0.0, 181.0, 5.0, "Longitude > 180"),
|
|
(0.0, -181.0, 5.0, "Longitude < -180"),
|
|
(0.0, 0.0, 5.0, "Null Island"),
|
|
(40.7128, -74.0060, 100.0, "Poor accuracy"),
|
|
]
|
|
|
|
|
|
# =============================================================================
|
|
# PYTEST MARKERS
|
|
# =============================================================================
|
|
|
|
def pytest_configure(config):
|
|
"""Register custom pytest markers"""
|
|
config.addinivalue_line("markers", "unit: Unit tests (fast, no external dependencies)")
|
|
config.addinivalue_line("markers", "integration: Integration tests (database, API)")
|
|
config.addinivalue_line("markers", "manual: Manual tests (human verification required)")
|
|
config.addinivalue_line("markers", "slow: Slow tests (skip in CI)")
|