181 lines
6.7 KiB
Python
181 lines
6.7 KiB
Python
"""
|
|
Integration tests for Phase 1 components.
|
|
|
|
These tests require a running PostgreSQL database with the test schema.
|
|
"""
|
|
|
|
import pytest
|
|
import pytest_asyncio
|
|
from typing import Dict, Any
|
|
|
|
from src.database.client import DatabaseClient
|
|
from src.core.auto_discovery import AutoDiscovery
|
|
from src.core.safety import SafetyLimitEnforcer
|
|
from config.settings import settings
|
|
|
|
|
|
@pytest.mark.integration
|
|
@pytest.mark.database
|
|
class TestPhase1Integration:
|
|
"""Integration tests for Phase 1 components."""
|
|
|
|
@pytest_asyncio.fixture(scope="class")
|
|
async def integration_db_client(self):
|
|
"""Create database client for integration tests."""
|
|
client = DatabaseClient(
|
|
database_url=settings.database_url,
|
|
min_connections=1,
|
|
max_connections=3
|
|
)
|
|
await client.connect()
|
|
yield client
|
|
await client.disconnect()
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_database_connection_integration(self, integration_db_client):
|
|
"""Test database connection and basic operations."""
|
|
# Test health check
|
|
assert integration_db_client.health_check() is True
|
|
|
|
# Test connection stats
|
|
stats = integration_db_client.get_connection_stats()
|
|
assert stats["pool_status"] == "active"
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_database_queries_integration(self, integration_db_client):
|
|
"""Test database queries with real database."""
|
|
# Test getting pump stations
|
|
stations = integration_db_client.get_pump_stations()
|
|
assert isinstance(stations, list)
|
|
|
|
# Test getting pumps
|
|
pumps = integration_db_client.get_pumps()
|
|
assert isinstance(pumps, list)
|
|
|
|
# Test getting safety limits
|
|
safety_limits = integration_db_client.get_safety_limits()
|
|
assert isinstance(safety_limits, list)
|
|
|
|
# Test getting pump plans
|
|
pump_plans = integration_db_client.get_latest_pump_plans()
|
|
assert isinstance(pump_plans, list)
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_auto_discovery_integration(self, integration_db_client):
|
|
"""Test auto-discovery with real database."""
|
|
auto_discovery = AutoDiscovery(integration_db_client, refresh_interval_minutes=5)
|
|
|
|
await auto_discovery.discover()
|
|
|
|
# Verify discovery was successful
|
|
stations = auto_discovery.get_stations()
|
|
pumps = auto_discovery.get_pumps()
|
|
|
|
assert isinstance(stations, dict)
|
|
assert isinstance(pumps, list)
|
|
|
|
# Verify discovery status
|
|
status = auto_discovery.get_discovery_status()
|
|
assert status["last_discovery"] is not None
|
|
assert status["station_count"] >= 0
|
|
assert status["pump_count"] >= 0
|
|
|
|
# Validate discovery data
|
|
validation = auto_discovery.validate_discovery()
|
|
assert isinstance(validation, dict)
|
|
assert "valid" in validation
|
|
assert "issues" in validation
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_safety_framework_integration(self, integration_db_client):
|
|
"""Test safety framework with real database."""
|
|
safety_enforcer = SafetyLimitEnforcer(integration_db_client)
|
|
|
|
await safety_enforcer.load_safety_limits()
|
|
|
|
# Verify limits were loaded
|
|
limits_count = safety_enforcer.get_loaded_limits_count()
|
|
assert limits_count >= 0
|
|
|
|
# Test setpoint enforcement if we have limits
|
|
if limits_count > 0:
|
|
# Get first pump with safety limits
|
|
auto_discovery = AutoDiscovery(integration_db_client)
|
|
await auto_discovery.discover()
|
|
pumps = auto_discovery.get_pumps()
|
|
|
|
if pumps:
|
|
pump = pumps[0]
|
|
station_id = pump['station_id']
|
|
pump_id = pump['pump_id']
|
|
|
|
# Test setpoint enforcement
|
|
enforced, violations = safety_enforcer.enforce_setpoint(
|
|
station_id, pump_id, 35.0
|
|
)
|
|
|
|
assert isinstance(enforced, float)
|
|
assert isinstance(violations, list)
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_component_interaction(self, integration_db_client):
|
|
"""Test interaction between Phase 1 components."""
|
|
# Initialize all components
|
|
auto_discovery = AutoDiscovery(integration_db_client)
|
|
safety_enforcer = SafetyLimitEnforcer(integration_db_client)
|
|
|
|
# Perform discovery
|
|
await auto_discovery.discover()
|
|
await safety_enforcer.load_safety_limits()
|
|
|
|
# Get discovered pumps
|
|
pumps = auto_discovery.get_pumps()
|
|
|
|
# Test setpoint enforcement for discovered pumps
|
|
for pump in pumps[:2]: # Test first 2 pumps
|
|
station_id = pump['station_id']
|
|
pump_id = pump['pump_id']
|
|
|
|
# Test setpoint enforcement
|
|
enforced, violations = safety_enforcer.enforce_setpoint(
|
|
station_id, pump_id, pump['default_setpoint_hz']
|
|
)
|
|
|
|
# Verify results
|
|
assert isinstance(enforced, float)
|
|
assert isinstance(violations, list)
|
|
|
|
# If we have safety limits, the enforced setpoint should be valid
|
|
if safety_enforcer.has_safety_limits(station_id, pump_id):
|
|
limits = safety_enforcer.get_safety_limits(station_id, pump_id)
|
|
assert limits.hard_min_speed_hz <= enforced <= limits.hard_max_speed_hz
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_error_handling_integration(self, integration_db_client):
|
|
"""Test error handling with real database."""
|
|
# Test invalid query
|
|
with pytest.raises(Exception):
|
|
integration_db_client.execute_query("SELECT * FROM non_existent_table")
|
|
|
|
# Test auto-discovery with invalid station filter
|
|
auto_discovery = AutoDiscovery(integration_db_client)
|
|
await auto_discovery.discover()
|
|
|
|
# Get pumps for non-existent station
|
|
pumps = auto_discovery.get_pumps("NON_EXISTENT_STATION")
|
|
assert pumps == []
|
|
|
|
# Get non-existent pump
|
|
pump = auto_discovery.get_pump("NON_EXISTENT_STATION", "NON_EXISTENT_PUMP")
|
|
assert pump is None
|
|
|
|
# Test safety enforcement for non-existent pump
|
|
safety_enforcer = SafetyLimitEnforcer(integration_db_client)
|
|
await safety_enforcer.load_safety_limits()
|
|
|
|
enforced, violations = safety_enforcer.enforce_setpoint(
|
|
"NON_EXISTENT_STATION", "NON_EXISTENT_PUMP", 35.0
|
|
)
|
|
|
|
assert enforced == 0.0
|
|
assert violations == ["NO_SAFETY_LIMITS_DEFINED"] |