solar-intelligence / tests /test_dashboard.py
ghostieee11's picture
Upload folder using huggingface_hub
15b595e verified
Raw
History Blame Contribute Delete
11.3 kB
"""Tests for dashboard components and Lumen integration.
Tests UI component construction, dashboard initialization, and
Lumen Source/Transform functionality without requiring a running server.
"""
from __future__ import annotations
import pandas as pd
import pytest
from solar_intelligence.ai_engine import SolarAIEngine
from solar_intelligence.data_loader import generate_synthetic_solar_data
from solar_intelligence.ui.components import (
FinancialConfigurator,
KPICard,
LocationPicker,
PanelConfigurator,
)
# ---------------------------------------------------------------------------
# Component Tests
# ---------------------------------------------------------------------------
class TestLocationPicker:
def test_default_values(self):
lp = LocationPicker()
assert lp.latitude == 0.0
assert lp.longitude == 0.0
def test_custom_coords(self):
lp = LocationPicker(latitude=40.7, longitude=-74.0, location_name="NYC")
assert lp.latitude == 40.7
assert lp.longitude == -74.0
assert lp.location_name == "NYC"
def test_panel_property_returns_column(self):
lp = LocationPicker()
panel = lp.panel
assert panel is not None
# Should be a pn.Column
assert hasattr(panel, 'objects')
class TestPanelConfigurator:
def test_default_params(self):
pc = PanelConfigurator()
assert pc.panel_efficiency == 0.20
assert pc.num_panels == 10
assert pc.direction == "South"
def test_custom_params(self):
pc = PanelConfigurator(panel_efficiency=0.22, num_panels=20, direction="East")
assert pc.panel_efficiency == 0.22
assert pc.num_panels == 20
assert pc.direction == "East"
def test_panel_property(self):
pc = PanelConfigurator()
panel = pc.panel
assert panel is not None
class TestFinancialConfigurator:
def test_defaults(self):
fc = FinancialConfigurator()
# Default currency is INR
assert fc.currency == "INR"
assert fc.system_cost == 500000 # ₹5 lakh
assert fc.electricity_rate == 8.0 # ₹8/kWh
assert fc.currency_symbol == "₹"
def test_panel_property(self):
fc = FinancialConfigurator()
panel = fc.panel
assert panel is not None
class TestKPICard:
def test_create_returns_column(self):
card = KPICard.create("Test Metric", "42", "units", "#FF0000")
assert card is not None
assert hasattr(card, 'objects')
def test_card_with_empty_subtitle(self):
card = KPICard.create("Title", "99", "")
assert card is not None
# ---------------------------------------------------------------------------
# AI Engine Tests
# ---------------------------------------------------------------------------
class TestAIEngine:
def test_template_mode_default(self):
ai = SolarAIEngine()
assert ai.mode == "template"
def test_generate_report(self):
ai = SolarAIEngine()
solar = {
"location": {"latitude": 28.6, "longitude": 77.2},
"average_daily_ghi": 5.5,
"average_daily_dni": 4.0,
"average_daily_dhi": 2.0,
"annual_solar_energy_kwh_m2": 2000,
"best_month": "Jun",
"best_month_ghi": 8.0,
"worst_month": "Dec",
"worst_month_ghi": 3.0,
"seasonal_ratio": 2.7,
}
energy = {
"system": {"capacity_kw": 6.8, "num_panels": 20, "total_area_m2": 34,
"panel_efficiency": 0.2, "system_losses": 0.14},
"production": {"annual_energy_kwh": 9000, "avg_daily_energy_kwh": 24.7,
"best_month": "Jun", "best_month_energy_kwh": 1000,
"worst_month": "Dec", "worst_month_energy_kwh": 500},
"performance": {"capacity_factor_pct": 15.1, "specific_yield_kwh_kwp": 1324},
}
financial = {
"investment": {"system_cost": 20000, "incentive": 6000, "net_cost": 14000},
"returns": {"first_year_savings": 1080, "payback_years": 12.5,
"npv_25yr": 5000, "roi_pct": 130},
"environmental": {"annual_co2_offset_kg": 3780, "lifetime_co2_offset_tonnes": 90,
"equivalent_trees": 172, "equivalent_car_miles_avoided": 9356},
}
orientation = {
"best_direction": "South", "best_tilt": 30, "best_azimuth": 180,
"annual_energy_kwh": 10000,
"energy_gain_vs_horizontal_pct": 5.0,
"energy_gain_vs_worst_pct": 45.0,
"worst_direction": "North", "worst_tilt": 90,
}
report = ai.generate_report(solar, energy, financial, orientation)
assert isinstance(report, str)
assert len(report) > 500
assert "Solar Resource Assessment" in report
assert "System Performance" in report
assert "Orientation Recommendation" in report
assert "Financial Analysis" in report
assert "Environmental Impact" in report
assert "South" in report
assert "5.50" in report or "5.5" in report
def test_generate_report_without_orientation(self):
ai = SolarAIEngine()
solar = {
"location": {"latitude": 28.6, "longitude": 77.2},
"average_daily_ghi": 5.5, "average_daily_dni": 4.0,
"average_daily_dhi": 2.0, "annual_solar_energy_kwh_m2": 2000,
"best_month": "Jun", "best_month_ghi": 8.0,
"worst_month": "Dec", "worst_month_ghi": 3.0,
"seasonal_ratio": 2.7,
}
energy = {
"system": {"capacity_kw": 3.4, "num_panels": 10, "total_area_m2": 17,
"panel_efficiency": 0.2, "system_losses": 0.14},
"production": {"annual_energy_kwh": 5000, "avg_daily_energy_kwh": 13.7,
"best_month": "Jun", "best_month_energy_kwh": 600,
"worst_month": "Dec", "worst_month_energy_kwh": 300},
"performance": {"capacity_factor_pct": 16.8, "specific_yield_kwh_kwp": 1471},
}
financial = {
"investment": {"system_cost": 10000, "incentive": 3000, "net_cost": 7000},
"returns": {"first_year_savings": 600, "payback_years": 11,
"npv_25yr": 2000, "roi_pct": 100},
"environmental": {"annual_co2_offset_kg": 2100, "lifetime_co2_offset_tonnes": 50,
"equivalent_trees": 95, "equivalent_car_miles_avoided": 5198},
}
report = ai.generate_report(solar, energy, financial)
assert "Orientation" not in report
def test_quick_insight_ghi(self):
ai = SolarAIEngine()
insight = ai.quick_insight("ghi", 5.5)
assert "5.5" in insight
assert "good" in insight
def test_quick_insight_payback(self):
ai = SolarAIEngine()
insight = ai.quick_insight("payback", 7.0)
assert "7.0" in insight
def test_quick_insight_unknown_metric(self):
ai = SolarAIEngine()
insight = ai.quick_insight("unknown_metric", 42)
assert "42" in insight
def test_classify_irradiance_levels(self):
ai = SolarAIEngine()
assert ai._classify_irradiance(7.0) == "excellent"
assert ai._classify_irradiance(5.0) == "good"
assert ai._classify_irradiance(3.5) == "moderate"
assert ai._classify_irradiance(1.0) == "low"
# ---------------------------------------------------------------------------
# Lumen Source/Transform Tests
# ---------------------------------------------------------------------------
class TestLumenIntegration:
def test_solar_data_source_tables(self):
from solar_intelligence.ui.lumen_app import SolarDataSource
source = SolarDataSource(latitude=28.6, longitude=77.2)
tables = source.get_tables()
assert "daily_solar" in tables
assert "monthly_solar" in tables
assert "metadata" in tables
def test_solar_data_source_schema(self):
from solar_intelligence.ui.lumen_app import SolarDataSource
source = SolarDataSource()
schema = source.get_schema("daily_solar")
assert "ALLSKY_SFC_SW_DWN" in schema
assert "T2M" in schema
def test_solar_data_source_get_daily(self):
from solar_intelligence.ui.lumen_app import SolarDataSource
source = SolarDataSource(use_synthetic=True, start_year=2023, end_year=2023)
df = source.get("daily_solar")
assert isinstance(df, pd.DataFrame)
assert "ALLSKY_SFC_SW_DWN" in df.columns
assert len(df) == 365
def test_solar_data_source_get_monthly(self):
from solar_intelligence.ui.lumen_app import SolarDataSource
source = SolarDataSource(use_synthetic=True, start_year=2023, end_year=2023)
df = source.get("monthly_solar")
assert isinstance(df, pd.DataFrame)
assert len(df) == 12
assert "GHI" in df.columns
def test_solar_data_source_get_metadata(self):
from solar_intelligence.ui.lumen_app import SolarDataSource
source = SolarDataSource(use_synthetic=True)
df = source.get("metadata")
assert "latitude" in df["key"].values
def test_solar_data_source_unknown_table(self):
from solar_intelligence.ui.lumen_app import SolarDataSource
source = SolarDataSource(use_synthetic=True)
with pytest.raises(ValueError, match="Unknown table"):
source.get("nonexistent")
def test_solar_energy_transform(self):
from solar_intelligence.ui.lumen_app import SolarDataSource, SolarEnergyTransform
source = SolarDataSource(use_synthetic=True, start_year=2023, end_year=2023)
df = source.get("daily_solar")
transform = SolarEnergyTransform(panel_efficiency=0.20, total_area=17.0)
result = transform.apply(df)
assert "energy_kwh" in result.columns
assert all(result["energy_kwh"] >= 0)
def test_monthly_aggregate_transform(self):
from solar_intelligence.ui.lumen_app import SolarDataSource, MonthlyAggregateTransform
source = SolarDataSource(use_synthetic=True, start_year=2023, end_year=2023)
df = source.get("daily_solar")
transform = MonthlyAggregateTransform(
value_columns=["ALLSKY_SFC_SW_DWN"],
)
result = transform.apply(df)
assert "month" in result.columns
assert "month_name" in result.columns
assert len(result) == 12
def test_anomaly_transform(self):
from solar_intelligence.ui.lumen_app import SolarDataSource, AnomalyTransform
source = SolarDataSource(use_synthetic=True, start_year=2023, end_year=2023)
df = source.get("daily_solar")
transform = AnomalyTransform()
result = transform.apply(df)
assert "anomaly" in result.columns
assert "climatology" in result.columns
def test_pipeline_creation(self):
from solar_intelligence.ui.lumen_app import create_solar_pipeline
pipeline = create_solar_pipeline(latitude=28.6, longitude=77.2)
assert pipeline is not None
assert pipeline.source is not None