diff --git a/tests/unit/test_update_equipment_simulation.py b/tests/unit/test_update_equipment_simulation.py new file mode 100644 index 0000000..253e0fd --- /dev/null +++ b/tests/unit/test_update_equipment_simulation.py @@ -0,0 +1,171 @@ +import pytest +from unittest.mock import AsyncMock, MagicMock, patch +from src.aeros_equipment.service import update_equipment_for_simulation +from src.aeros_equipment.model import AerosEquipment, AerosEquipmentGroup, ReliabilityPredictNonRepairable +from src.aeros_simulation.model import AerosNode +import logging + +@pytest.mark.asyncio +async def test_update_equipment_for_simulation_basic(mocker): + # Mock parameters + db_session = AsyncMock() + aeros_db_session = AsyncMock() + project_name = "TestProject" + simulation_duration = 8760 + overhaul_duration = 72 + overhaul_interval = 8000 + offset = 0 + schematic_name = "TestSchematic" + + # Mock get_aeros_schematic_by_name + mock_schematic = MagicMock() + mock_schematic.id = 1 + mocker.patch("src.aeros_equipment.service.get_aeros_schematic_by_name", return_value=mock_schematic) + + # Mock db_session.execute for equipments + mock_eq = MagicMock() + mock_eq.location_tag = "EQ001" + + mock_eq_result = MagicMock() + mock_eq_result.scalars.return_value.all.return_value = [mock_eq] + + # Mock db_session.execute for rbd_group + mock_group = MagicMock() + mock_group.group_name = "GROUP001" + + mock_group_result = MagicMock() + mock_group_result.scalars.return_value.all.return_value = [mock_group] + + # Mock db_session.execute for non_repairable + mock_nr_result = MagicMock() + mock_nr_result.scalars.return_value.all.return_value = [] + + db_session.execute.side_effect = [ + mock_eq_result, # for equipments + mock_group_result, # for rbd_group + mock_nr_result # for non_repairable + ] + + # Mock get_aeros_equipment_by_location_tag + mock_nodes_data = [ + {"equipmentName": "EQ001", "relDisType": "Fixed", "relDisP1": 0}, + {"equipmentName": "GROUP001", "relDisType": "Fixed", "relDisP1": 0} + ] + mocker.patch("src.aeros_equipment.service.get_aeros_equipment_by_location_tag", return_value=mock_nodes_data) + + # Mock get_asset_batch + mock_reliability_data = { + "EQ001": { + "relDisType": "Weibull2", + "relDisP1": 1.5, + "relDisP2": 10000, + "cmDisType": "Fixed", + "cmDisP1": 5, + "cmDisP2": 0 + } + } + mocker.patch("src.aeros_equipment.service.get_asset_batch", return_value=mock_reliability_data) + + # Mock update_oh_interval_offset + mocker.patch("src.aeros_equipment.service.update_oh_interval_offset", return_value=None) + + # Mock update_node + mock_update_node = mocker.patch("src.aeros_equipment.service.update_node", return_value=None) + + # Run the function + results = await update_equipment_for_simulation( + db_session=db_session, + aeros_db_session=aeros_db_session, + project_name=project_name, + simulation_duration=simulation_duration, + overhaul_duration=overhaul_duration, + overhaul_interval=overhaul_interval, + offset=offset, + schematic_name=schematic_name + ) + + # Assertions + assert "EQ001" in results + assert results["EQ001"]["distribution"] == "Weibull2" + assert results["EQ001"]["oh_duration"] == overhaul_duration + + # Check if update_node was called with correct arguments + called_args = mock_update_node.call_args[1] + equipment_nodes = called_args["equipment_nodes"] + + # Find EQ001 in equipment_nodes + eq001_node = next(node for node in equipment_nodes if node["equipmentName"] == "EQ001") + assert eq001_node["relDisType"] == "Weibull2" + assert eq001_node["ohDisP1"] == overhaul_duration + assert eq001_node["relDisUnitCode"] == "UHour" + assert eq001_node["ohDisUnitCode"] == "UHour" + +@pytest.mark.asyncio +async def test_update_equipment_for_simulation_custom_input(mocker): + # Mock parameters + db_session = AsyncMock() + aeros_db_session = AsyncMock() + project_name = "TestProject" + simulation_duration = 8760 + overhaul_duration = 72 + overhaul_interval = 8000 + offset = 0 + schematic_name = "TestSchematic" + + custom_input = { + "EQ001": { + "mttr": 10, + "failure_rate": 0.5, + "distribution": "Exponential2" + } + } + + # Mock get_aeros_schematic_by_name + mock_schematic = MagicMock() + mock_schematic.id = 1 + mocker.patch("src.aeros_equipment.service.get_aeros_schematic_by_name", return_value=mock_schematic) + + # Mock db_session.execute + mock_eq = MagicMock() + mock_eq.location_tag = "EQ001" + + mock_eq_result = MagicMock() + mock_eq_result.scalars.return_value.all.return_value = [mock_eq] + + mock_empty_result = MagicMock() + mock_empty_result.scalars.return_value.all.return_value = [] + + db_session.execute.side_effect = [ + mock_eq_result, # equipments + mock_empty_result, # rbd_group + mock_empty_result # non_repairable + ] + + # Mock get_aeros_equipment_by_location_tag + mock_nodes_data = [ + {"equipmentName": "EQ001", "relDisType": "Fixed", "relDisP1": 0} + ] + mocker.patch("src.aeros_equipment.service.get_aeros_equipment_by_location_tag", return_value=mock_nodes_data) + + # Mock get_asset_batch (should be called but maybe ignored if custom input matches) + mocker.patch("src.aeros_equipment.service.get_asset_batch", return_value={}) + + mocker.patch("src.aeros_equipment.service.update_oh_interval_offset", return_value=None) + mock_update_node = mocker.patch("src.aeros_equipment.service.update_node", return_value=None) + + # Run + results = await update_equipment_for_simulation( + db_session=db_session, + aeros_db_session=aeros_db_session, + project_name=project_name, + simulation_duration=simulation_duration, + overhaul_duration=overhaul_duration, + overhaul_interval=overhaul_interval, + offset=offset, + schematic_name=schematic_name, + custom_input=custom_input + ) + + assert "EQ001" in results + assert results["EQ001"]["mttr"] == 10 + assert results["EQ001"]["distribution"] == "Exponential2"