CalejoControl/tests/integration/test_phase1_integration.py

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"]