Add comprehensive testing infrastructure

- 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
This commit is contained in:
2026-01-12 11:25:13 -08:00
parent eb225771bc
commit 64ce279a2e
5 changed files with 1494 additions and 0 deletions
+187
View File
@@ -0,0 +1,187 @@
"""
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)")