| """ |
| Test script for HVAC Load Calculator. |
| This script tests the functionality of the HVAC Load Calculator. |
| """ |
|
|
| import os |
| import sys |
| import json |
| import unittest |
| from pathlib import Path |
|
|
| |
| sys.path.append(str(Path(__file__).parent.parent)) |
|
|
| |
| from models.building import Building, CoolingLoadResult |
| from controllers.enhanced_cooling_load_calculator import calculate_cooling_load |
| from controllers.monthly_breakdown import calculate_monthly_breakdown |
| from utils.data_io import export_building_to_json, import_building_from_json |
| from utils.data_io import export_result_to_json, import_result_from_json |
| from utils.data_io import export_monthly_breakdown_to_csv |
| from utils.data_io import create_project_archive |
|
|
| class TestBuildingModel(unittest.TestCase): |
| """Test cases for Building model.""" |
| |
| def setUp(self): |
| """Set up test fixtures.""" |
| |
| self.building = Building() |
| self.building.settings.name = "Test Building" |
| self.building.settings.floor_area = 100 |
| self.building.settings.ceiling_height = 3 |
| self.building.settings.indoor_temp = 24 |
| self.building.settings.indoor_humidity = 50 |
| |
| self.building.location.city = "New York" |
| self.building.location.latitude = 40.7128 |
| self.building.location.longitude = -74.0060 |
| |
| |
| self.building.add_wall("North", 10, 3, 0.5, "Medium") |
| self.building.add_wall("South", 10, 3, 0.5, "Medium") |
| self.building.add_wall("East", 10, 3, 0.5, "Medium") |
| self.building.add_wall("West", 10, 3, 0.5, "Medium") |
| |
| |
| self.building.roof.area = 100 |
| self.building.roof.u_value = 0.3 |
| self.building.roof.construction_type = "Medium" |
| |
| |
| self.building.add_glass("North", 2, 1.5, 0.4, 0.8, "Single") |
| self.building.add_glass("South", 2, 1.5, 0.4, 0.8, "Single") |
| |
| |
| self.building.people.count = 5 |
| self.building.people.activity = "Office Work" |
| |
| |
| self.building.lighting.power = 500 |
| self.building.lighting.type = "LED" |
| |
| |
| self.building.equipment.power = 1000 |
| self.building.equipment.type = "General" |
| |
| def test_building_creation(self): |
| """Test building creation.""" |
| self.assertEqual(self.building.settings.name, "Test Building") |
| self.assertEqual(self.building.settings.floor_area, 100) |
| self.assertEqual(self.building.settings.ceiling_height, 3) |
| self.assertEqual(self.building.settings.indoor_temp, 24) |
| self.assertEqual(self.building.settings.indoor_humidity, 50) |
| |
| self.assertEqual(self.building.location.city, "New York") |
| self.assertEqual(self.building.location.latitude, 40.7128) |
| self.assertEqual(self.building.location.longitude, -74.0060) |
| |
| self.assertEqual(len(self.building.walls), 4) |
| self.assertEqual(self.building.walls[0].orientation, "North") |
| self.assertEqual(self.building.walls[0].area, 30) |
| self.assertEqual(self.building.walls[0].u_value, 0.5) |
| |
| self.assertEqual(self.building.roof.area, 100) |
| self.assertEqual(self.building.roof.u_value, 0.3) |
| |
| self.assertEqual(len(self.building.glass), 2) |
| self.assertEqual(self.building.glass[0].orientation, "North") |
| self.assertEqual(self.building.glass[0].area, 3) |
| self.assertEqual(self.building.glass[0].u_value, 1.5) |
| self.assertEqual(self.building.glass[0].shgc, 0.4) |
| |
| self.assertEqual(self.building.people.count, 5) |
| self.assertEqual(self.building.people.activity, "Office Work") |
| |
| self.assertEqual(self.building.lighting.power, 500) |
| self.assertEqual(self.building.lighting.type, "LED") |
| |
| self.assertEqual(self.building.equipment.power, 1000) |
| self.assertEqual(self.building.equipment.type, "General") |
| |
| def test_building_to_dict(self): |
| """Test building to dictionary conversion.""" |
| building_dict = self.building.to_dict() |
| |
| self.assertEqual(building_dict["settings"]["name"], "Test Building") |
| self.assertEqual(building_dict["settings"]["floor_area"], 100) |
| self.assertEqual(building_dict["settings"]["ceiling_height"], 3) |
| self.assertEqual(building_dict["settings"]["indoor_temp"], 24) |
| self.assertEqual(building_dict["settings"]["indoor_humidity"], 50) |
| |
| self.assertEqual(building_dict["location"]["city"], "New York") |
| self.assertEqual(building_dict["location"]["latitude"], 40.7128) |
| self.assertEqual(building_dict["location"]["longitude"], -74.0060) |
| |
| self.assertEqual(len(building_dict["walls"]), 4) |
| self.assertEqual(building_dict["walls"][0]["orientation"], "North") |
| self.assertEqual(building_dict["walls"][0]["area"], 30) |
| self.assertEqual(building_dict["walls"][0]["u_value"], 0.5) |
| |
| self.assertEqual(building_dict["roof"]["area"], 100) |
| self.assertEqual(building_dict["roof"]["u_value"], 0.3) |
| |
| self.assertEqual(len(building_dict["glass"]), 2) |
| self.assertEqual(building_dict["glass"][0]["orientation"], "North") |
| self.assertEqual(building_dict["glass"][0]["area"], 3) |
| self.assertEqual(building_dict["glass"][0]["u_value"], 1.5) |
| self.assertEqual(building_dict["glass"][0]["shgc"], 0.4) |
| |
| self.assertEqual(building_dict["people"]["count"], 5) |
| self.assertEqual(building_dict["people"]["activity"], "Office Work") |
| |
| self.assertEqual(building_dict["lighting"]["power"], 500) |
| self.assertEqual(building_dict["lighting"]["type"], "LED") |
| |
| self.assertEqual(building_dict["equipment"]["power"], 1000) |
| self.assertEqual(building_dict["equipment"]["type"], "General") |
| |
| def test_building_from_dict(self): |
| """Test building from dictionary conversion.""" |
| building_dict = self.building.to_dict() |
| new_building = Building.from_dict(building_dict) |
| |
| self.assertEqual(new_building.settings.name, "Test Building") |
| self.assertEqual(new_building.settings.floor_area, 100) |
| self.assertEqual(new_building.settings.ceiling_height, 3) |
| self.assertEqual(new_building.settings.indoor_temp, 24) |
| self.assertEqual(new_building.settings.indoor_humidity, 50) |
| |
| self.assertEqual(new_building.location.city, "New York") |
| self.assertEqual(new_building.location.latitude, 40.7128) |
| self.assertEqual(new_building.location.longitude, -74.0060) |
| |
| self.assertEqual(len(new_building.walls), 4) |
| self.assertEqual(new_building.walls[0].orientation, "North") |
| self.assertEqual(new_building.walls[0].area, 30) |
| self.assertEqual(new_building.walls[0].u_value, 0.5) |
| |
| self.assertEqual(new_building.roof.area, 100) |
| self.assertEqual(new_building.roof.u_value, 0.3) |
| |
| self.assertEqual(len(new_building.glass), 2) |
| self.assertEqual(new_building.glass[0].orientation, "North") |
| self.assertEqual(new_building.glass[0].area, 3) |
| self.assertEqual(new_building.glass[0].u_value, 1.5) |
| self.assertEqual(new_building.glass[0].shgc, 0.4) |
| |
| self.assertEqual(new_building.people.count, 5) |
| self.assertEqual(new_building.people.activity, "Office Work") |
| |
| self.assertEqual(new_building.lighting.power, 500) |
| self.assertEqual(new_building.lighting.type, "LED") |
| |
| self.assertEqual(new_building.equipment.power, 1000) |
| self.assertEqual(new_building.equipment.type, "General") |
|
|
| class TestCoolingLoadCalculator(unittest.TestCase): |
| """Test cases for cooling load calculator.""" |
| |
| def setUp(self): |
| """Set up test fixtures.""" |
| |
| self.building = Building() |
| self.building.settings.name = "Test Building" |
| self.building.settings.floor_area = 100 |
| self.building.settings.ceiling_height = 3 |
| self.building.settings.indoor_temp = 24 |
| self.building.settings.indoor_humidity = 50 |
| |
| self.building.location.city = "New York" |
| self.building.location.latitude = 40.7128 |
| self.building.location.longitude = -74.0060 |
| |
| |
| self.building.add_wall("North", 10, 3, 0.5, "Medium") |
| self.building.add_wall("South", 10, 3, 0.5, "Medium") |
| self.building.add_wall("East", 10, 3, 0.5, "Medium") |
| self.building.add_wall("West", 10, 3, 0.5, "Medium") |
| |
| |
| self.building.roof.area = 100 |
| self.building.roof.u_value = 0.3 |
| self.building.roof.construction_type = "Medium" |
| |
| |
| self.building.add_glass("North", 2, 1.5, 0.4, 0.8, "Single") |
| self.building.add_glass("South", 2, 1.5, 0.4, 0.8, "Single") |
| |
| |
| self.building.people.count = 5 |
| self.building.people.activity = "Office Work" |
| |
| |
| self.building.lighting.power = 500 |
| self.building.lighting.type = "LED" |
| |
| |
| self.building.equipment.power = 1000 |
| self.building.equipment.type = "General" |
| |
| def test_cooling_load_calculation(self): |
| """Test cooling load calculation.""" |
| |
| result = calculate_cooling_load(self.building) |
| |
| |
| self.assertIsNotNone(result) |
| self.assertEqual(result.building_name, "Test Building") |
| self.assertGreater(result.peak_sensible_load, 0) |
| self.assertGreater(result.peak_latent_load, 0) |
| self.assertGreater(result.peak_total_load, 0) |
| self.assertGreaterEqual(result.peak_hour, 0) |
| self.assertLessEqual(result.peak_hour, 23) |
| |
| |
| self.assertIn("roof", result.external_loads) |
| self.assertIn("walls_total", result.external_loads) |
| self.assertIn("glass_conduction_total", result.external_loads) |
| self.assertIn("glass_solar_total", result.external_loads) |
| |
| |
| self.assertIn("people_sensible", result.internal_loads) |
| self.assertIn("people_latent", result.internal_loads) |
| self.assertIn("lighting", result.internal_loads) |
| self.assertIn("equipment_sensible", result.internal_loads) |
| self.assertIn("equipment_latent", result.internal_loads) |
| self.assertIn("sensible_total", result.internal_loads) |
| self.assertIn("latent_total", result.internal_loads) |
| |
| def test_monthly_breakdown_calculation(self): |
| """Test monthly breakdown calculation.""" |
| |
| monthly_breakdown = calculate_monthly_breakdown(self.building) |
| |
| |
| self.assertIsNotNone(monthly_breakdown) |
| self.assertIn("Jan", monthly_breakdown) |
| self.assertIn("Feb", monthly_breakdown) |
| self.assertIn("Mar", monthly_breakdown) |
| self.assertIn("Apr", monthly_breakdown) |
| self.assertIn("May", monthly_breakdown) |
| self.assertIn("Jun", monthly_breakdown) |
| self.assertIn("Jul", monthly_breakdown) |
| self.assertIn("Aug", monthly_breakdown) |
| self.assertIn("Sep", monthly_breakdown) |
| self.assertIn("Oct", monthly_breakdown) |
| self.assertIn("Nov", monthly_breakdown) |
| self.assertIn("Dec", monthly_breakdown) |
| self.assertIn("annual", monthly_breakdown) |
| |
| |
| for month, data in monthly_breakdown.items(): |
| if month != "annual": |
| self.assertIn("energy_kwh", data) |
| self.assertIn("peak_load_w", data) |
| self.assertIn("average_load_w", data) |
| self.assertIn("avg_temp_c", data) |
| self.assertIn("cooling_degree_days", data) |
| |
| |
| annual = monthly_breakdown["annual"] |
| self.assertIn("energy_kwh", annual) |
| self.assertIn("peak_load_w", annual) |
| self.assertIn("average_load_w", annual) |
| self.assertIn("avg_temp_c", annual) |
| self.assertIn("cooling_degree_days", annual) |
|
|
| class TestDataIO(unittest.TestCase): |
| """Test cases for data import/export.""" |
| |
| def setUp(self): |
| """Set up test fixtures.""" |
| |
| self.building = Building() |
| self.building.settings.name = "Test Building" |
| self.building.settings.floor_area = 100 |
| self.building.settings.ceiling_height = 3 |
| self.building.settings.indoor_temp = 24 |
| self.building.settings.indoor_humidity = 50 |
| |
| self.building.location.city = "New York" |
| self.building.location.latitude = 40.7128 |
| self.building.location.longitude = -74.0060 |
| |
| |
| self.building.add_wall("North", 10, 3, 0.5, "Medium") |
| self.building.add_wall("South", 10, 3, 0.5, "Medium") |
| self.building.add_wall("East", 10, 3, 0.5, "Medium") |
| self.building.add_wall("West", 10, 3, 0.5, "Medium") |
| |
| |
| self.building.roof.area = 100 |
| self.building.roof.u_value = 0.3 |
| self.building.roof.construction_type = "Medium" |
| |
| |
| self.building.add_glass("North", 2, 1.5, 0.4, 0.8, "Single") |
| self.building.add_glass("South", 2, 1.5, 0.4, 0.8, "Single") |
| |
| |
| self.building.people.count = 5 |
| self.building.people.activity = "Office Work" |
| |
| |
| self.building.lighting.power = 500 |
| self.building.lighting.type = "LED" |
| |
| |
| self.building.equipment.power = 1000 |
| self.building.equipment.type = "General" |
| |
| |
| self.result = calculate_cooling_load(self.building) |
| |
| |
| self.monthly_breakdown = calculate_monthly_breakdown(self.building) |
| |
| |
| os.makedirs("test_output", exist_ok=True) |
| |
| def tearDown(self): |
| """Tear down test fixtures.""" |
| |
| for file in os.listdir("test_output"): |
| os.remove(os.path.join("test_output", file)) |
| |
| |
| os.rmdir("test_output") |
| |
| def test_building_export_import(self): |
| """Test building export and import.""" |
| |
| json_str = export_building_to_json(self.building) |
| |
| |
| file_path = os.path.join("test_output", "building.json") |
| with open(file_path, "w") as f: |
| f.write(json_str) |
| |
| |
| with open(file_path, "r") as f: |
| json_str = f.read() |
| |
| new_building = import_building_from_json(json_str) |
| |
| |
| self.assertEqual(new_building.settings.name, "Test Building") |
| self.assertEqual(new_building.settings.floor_area, 100) |
| self.assertEqual(new_building.settings.ceiling_height, 3) |
| self.assertEqual(new_building.settings.indoor_temp, 24) |
| self.assertEqual(new_building.settings.indoor_humidity, 50) |
| |
| self.assertEqual(new_building.location.city, "New York") |
| self.assertEqual(new_building.location.latitude, 40.7128) |
| self.assertEqual(new_building.location.longitude, -74.0060) |
| |
| self.assertEqual(len(new_building.walls), 4) |
| self.assertEqual(new_building.walls[0].orientation, "North") |
| self.assertEqual(new_building.walls[0].area, 30) |
| self.assertEqual(new_building.walls[0].u_value, 0.5) |
| |
| self.assertEqual(new_building.roof.area, 100) |
| self.assertEqual(new_building.roof.u_value, 0.3) |
| |
| self.assertEqual(len(new_building.glass), 2) |
| self.assertEqual(new_building.glass[0].orientation, "North") |
| self.assertEqual(new_building.glass[0].area, 3) |
| self.assertEqual(new_building.glass[0].u_value, 1.5) |
| self.assertEqual(new_building.glass[0].shgc, 0.4) |
| |
| self.assertEqual(new_building.people.count, 5) |
| self.assertEqual(new_building.people.activity, "Office Work") |
| |
| self.assertEqual(new_building.lighting.power, 500) |
| self.assertEqual(new_building.lighting.type, "LED") |
| |
| self.assertEqual(new_building.equipment.power, 1000) |
| self.assertEqual(new_building.equipment.type, "General") |
| |
| def test_result_export_import(self): |
| """Test result export and import.""" |
| |
| json_str = export_result_to_json(self.result) |
| |
| |
| file_path = os.path.join("test_output", "result.json") |
| with open(file_path, "w") as f: |
| f.write(json_str) |
| |
| |
| with open(file_path, "r") as f: |
| json_str = f.read() |
| |
| new_result = import_result_from_json(json_str) |
| |
| |
| self.assertEqual(new_result.building_name, "Test Building") |
| self.assertEqual(new_result.peak_sensible_load, self.result.peak_sensible_load) |
| self.assertEqual(new_result.peak_latent_load, self.result.peak_latent_load) |
| self.assertEqual(new_result.peak_total_load, self.result.peak_total_load) |
| self.assertEqual(new_result.peak_hour, self.result.peak_hour) |
| |
| def test_monthly_breakdown_export(self): |
| """Test monthly breakdown export.""" |
| |
| csv_str = export_monthly_breakdown_to_csv(self.monthly_breakdown) |
| |
| |
| file_path = os.path.join("test_output", "monthly_breakdown.csv") |
| with open(file_path, "w") as f: |
| f.write(csv_str) |
| |
| |
| self.assertTrue(os.path.exists(file_path)) |
| |
| def test_project_archive(self): |
| """Test project archive creation.""" |
| |
| zip_data = create_project_archive(self.building, self.result, self.monthly_breakdown) |
| |
| |
| file_path = os.path.join("test_output", "project.zip") |
| with open(file_path, "wb") as f: |
| f.write(zip_data) |
| |
| |
| self.assertTrue(os.path.exists(file_path)) |
|
|
| if __name__ == "__main__": |
| unittest.main() |
|
|