Skip to content

Commit

Permalink
Addressing comments
Browse files Browse the repository at this point in the history
  • Loading branch information
caleb-sitton-inl committed Jul 25, 2024
1 parent 126977c commit cdfa1a4
Showing 1 changed file with 73 additions and 93 deletions.
166 changes: 73 additions & 93 deletions tests/unit_tests/test_heron.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,36 @@
sys.path.append(FORCE_LOC)
from FORCE.src.heron import create_componentsets_in_HERON

class TestMinimalInput(unittest.TestCase):
class HERONTestCase(unittest.TestCase):

def check_reference_price(self, cashflow, correct_value, correct_content_length=1):
ref_price = cashflow.findall('./reference_price')
self.assertEqual(len(ref_price), 1)
ref_price_contents = [e for e in ref_price[0].findall('./')
if not e.tag is ET.Comment] # Filters out ET.Comment elements
self.assertEqual(len(ref_price_contents), correct_content_length)
ref_price_value = ref_price[0].findall('./fixed_value')
self.assertEqual(ref_price_value[0].text, correct_value)

def check_reference_driver(self, cashflow, correct_value, correct_content_length=1):
ref_driver = cashflow.findall('./reference_driver')
self.assertEqual(len(ref_driver), 1)
ref_driver_contents = [e for e in ref_driver[0].findall('./')
if not e.tag is ET.Comment] # Filters out ET.Comment elements
self.assertEqual(len(ref_driver_contents), correct_content_length)
ref_driver_value = ref_driver[0].findall('./fixed_value')
self.assertEqual(ref_driver_value[0].text, correct_value)

def check_scaling_factor(self, cashflow, correct_value, correct_content_length=1):
scaling_factor = cashflow.findall('./scaling_factor_x')
self.assertEqual(len(scaling_factor), 1)
scaling_factor_contents = [e for e in scaling_factor[0].findall('./')
if not e.tag is ET.Comment] # Filters out ET.Comment elements
self.assertEqual(len(scaling_factor_contents), correct_content_length)
scaling_factor_value = scaling_factor[0].findall('./fixed_value')
self.assertEqual(scaling_factor_value[0].text, correct_value)

class TestMinimalInput(HERONTestCase):

def setUp(self):
# Example of a minimal XML structure
Expand Down Expand Up @@ -56,17 +85,12 @@ def test_minimal_input(self, mock_file, mock_listdir, mock_parse):
self.assertIn('type', cashflows[0].keys())
self.assertIn('taxable', cashflows[0].keys())
self.assertIn('inflation', cashflows[0].keys())
self.assertIn('mult_target', cashflows[0].keys())

# Verify reference price
ref_price_value = cashflows[0].find('./reference_price/fixed_value')
self.assertEqual(ref_price_value.text, '-2000')

# Verify the reference driver and price updates
ref_driver_value = cashflows[0].find('./reference_driver/fixed_value')
self.assertEqual(ref_driver_value.text, '1.0') # The driver should have been converted from kW to MW
# Verify reference price and reference driver
self.check_reference_driver(cashflows[0], '1.0')
self.check_reference_price(cashflows[0], '-2000')

class TestExpandedInput1(unittest.TestCase):
class TestExpandedInput1(HERONTestCase):

def setUp(self):
# Added case and datagenerator nodes (should be transferred blindly) and extra components
Expand Down Expand Up @@ -120,7 +144,7 @@ def test_expanded_input_1(self, mock_open, mock_listdir, mock_parse):
result_tree = create_componentsets_in_HERON("/fake/folder", "/fake/heron_input.xml")

# Verify Case node was transferred
with (self.subTest("Case node has been corrupted")):
with self.subTest("Case node has been corrupted"):
cases = result_tree.findall('./Case')
self.assertEqual(len(cases), 1)
self.assertIsNotNone(cases[0].find('./untouched_content_Case'))
Expand All @@ -130,28 +154,26 @@ def test_expanded_input_1(self, mock_open, mock_listdir, mock_parse):
self.assertEqual(len(component_nodes), 3)

for comp in component_nodes:
cashflows = comp.findall('./economics/CashFlow')
if comp.get('name') == 'ExistingComponent0':
# Verify CashFlow with type
cashflows = comp.findall('./economics/CashFlow')
self.assertEqual(len(cashflows), 1)
self.assertEqual(cashflows[0].attrib['type'], 'one-time')
elif comp.get('name') == 'ExistingComponent1':
# Verify CashFlow with type
cashflows = comp.findall('./economics/CashFlow')
self.assertEqual(len(cashflows), 1)
self.assertEqual(cashflows[0].attrib['type'], 'repeating')
elif comp.get('name') == 'NewComponent':
# Verify reference driver
ref_driver = comp.find('./economics/CashFlow/reference_driver/fixed_value')
self.assertEqual(ref_driver.text, '1000') # Check that mW were not converted
self.check_reference_driver(cashflows[0], '1000')

# Verify DataGenerators node was transferred
with (self.subTest("DataGenerators node has been corrupted")):
with self.subTest("DataGenerators node has been corrupted"):
data_gens = result_tree.findall('./DataGenerators')
self.assertEqual(len(data_gens), 1)
self.assertIsNotNone(data_gens[0].find('./untouched_content_DG'))

class TestExpandedInput2(unittest.TestCase):
class TestExpandedInput2(HERONTestCase):

def setUp(self):
# Complex subnodes to each component with various <economics> and <CashFlows> positions and configurations
Expand Down Expand Up @@ -179,7 +201,7 @@ def setUp(self):
<Component name="Component2">
<economics>
<ProjectTime>1</ProjectTime>
<lifetime>1</lifetime>
<CashFlow name="capex_Comp2" npv_exempt="True">
<reference_driver>
<fixed_value>1234</fixed_value>
Expand Down Expand Up @@ -267,12 +289,13 @@ def test_expanded_input_2(self, mock_listdir, mock_parse):
self.assertEqual(len(component_nodes), 4)

for comp in component_nodes:
economics = comp.findall('./economics')
self.assertEqual(len(economics), 1)

if comp.get('name') == 'Component0':
economics = comp.find('./economics')

# Verify non-capex cashflow was not corrupted
with self.subTest("Non-capex CashFlow node was corrupted"):
cashflow_non_capex = economics.findall('./CashFlow[@name="other"]')
cashflow_non_capex = economics[0].findall('./CashFlow[@name="other"]')
self.assertEqual(len(cashflow_non_capex), 1)
cf_noncap_contents = [e for e in cashflow_non_capex[0].findall('./')
if not e.tag is ET.Comment] # Filters out ET.Comment elements
Expand All @@ -281,13 +304,10 @@ def test_expanded_input_2(self, mock_listdir, mock_parse):

# Verify capex cashflow was added
with self.subTest("capex CashFlow was not added correctly"):
cashflow_capex = economics.findall('./CashFlow[@name="Component0_capex"]')
cashflow_capex = economics[0].findall('./CashFlow[@name="Component0_capex"]')
self.assertEqual(len(cashflow_capex), 1)

elif comp.get('name') == 'Component1':
economics = comp.findall('./economics')
self.assertEqual(len(economics), 1)

# Verify number of cashflows
self.assertEqual(len(economics[0].findall('./CashFlow')), 2)

Expand All @@ -304,93 +324,56 @@ def test_expanded_input_2(self, mock_listdir, mock_parse):
with self.subTest("capex CashFlow node was not updated correctly"):
cashflow_capex = economics[0].findall('./CashFlow[@name="capex"]')
self.assertEqual(len(cashflow_capex), 1)
ref_price = cashflow_capex[0].findall('./reference_price/fixed_value')
self.assertEqual(ref_price[0].text, '-2200')
self.check_reference_price(cashflow_capex[0], '-2200')

elif comp.get('name') == 'Component2':
economics = comp.findall('./economics')

# Verify ProjectTime was not corrupted
# Verify lifetime was not corrupted
with self.subTest("Non-cashflow child node of economics has been corrupted"):
proj_time = economics[0].findall('./ProjectTime')
proj_time = economics[0].findall('./lifetime')
self.assertEqual(len(proj_time), 1)
self.assertEqual(proj_time[0].text, '1')

# Verify cashflow merging
cashflow = economics[0].findall('./CashFlow')
self.assertEqual(len(cashflow), 1)
cashflows = economics[0].findall('./CashFlow')
self.assertEqual(len(cashflows), 1)

# Verify cashflow was updated correctly

# Attributes
with self.subTest("Attributes of CashFlow were corrupted"):
self.assertIn('npv_exempt', cashflow[0].keys())
self.assertIn('npv_exempt', cashflows[0].keys())

# Children
with self.subTest("CashFlow children nodes were not updated correctly"):
cf_contents = [e for e in cashflow[0].findall('./')
cf_contents = [e for e in cashflows[0].findall('./')
if not e.tag is ET.Comment] # Filters out ET.Comment elements
self.assertEqual(len(cf_contents), 4)

# Reference driver
ref_driver = cashflow[0].findall('./reference_driver')
self.assertEqual(len(ref_driver), 1)
ref_driver_value = ref_driver[0].findall('./fixed_value')
self.assertEqual(ref_driver_value[0].text, '3100')

# Reference price
ref_price = cashflow[0].findall('./reference_price')
self.assertEqual(len(ref_price), 1)
ref_price_contents = [e for e in ref_price[0].findall('./')
if not e.tag is ET.Comment] # Filters out ET.Comment elements
self.assertEqual(len(ref_price_contents), 1)
ref_price_value = ref_price[0].findall('./fixed_value')
self.assertEqual(ref_price_value[0].text, '-3200')

# Scaling factor
scaling_factor = cashflow[0].findall('./scaling_factor_x')
self.assertEqual(len(scaling_factor), 1)
scaling_factor_contents = [e for e in scaling_factor[0].findall('./')
if not e.tag is ET.Comment] # Filters out ET.Comment elements
self.assertEqual(len(scaling_factor_contents), 1)
scaling_factor_value = scaling_factor[0].findall('./fixed_value')
self.assertEqual(scaling_factor_value[0].text, '0.3')
self.check_reference_driver(cashflows[0], '3100')
self.check_reference_price(cashflows[0], '-3200')
self.check_scaling_factor(cashflows[0], '0.3')

with self.subTest("Existing CashFlow child node was corrupted"):
# Driver node
driver = cashflow[0].findall('./driver')
driver = cashflows[0].findall('./driver')
self.assertEqual(len(driver), 1)
self.assertIsNotNone(driver[0].findall('fixed_value'))

elif comp.get('name') == 'Component3':
cashflow = comp.findall('./economics/CashFlow')
self.assertEqual(len(cashflow), 1)
cashflows = comp.findall('./economics/CashFlow')
self.assertEqual(len(cashflows), 1)

# Verify cashflow was updated correctly
with self.subTest("CashFlow children nodes were not updated correctly"):
cf_contents = [e for e in cashflow[0].findall('./')
cf_contents = [e for e in cashflows[0].findall('./')
if not e.tag is ET.Comment] # Filters out ET.Comment elements
self.assertEqual(len(cf_contents), 3)

# Reference driver
ref_driver = cashflow[0].findall('./reference_driver')
self.assertEqual(len(ref_driver), 1)
ref_driver_value = ref_driver[0].findall('./fixed_value')
self.assertEqual(ref_driver_value[0].text, '4100')
self.check_reference_driver(cashflows[0], '4100')
self.check_reference_price(cashflows[0], '-4200')
self.check_scaling_factor(cashflows[0], '0.4')

# Reference price
ref_price = cashflow[0].findall('./reference_price')
self.assertEqual(len(ref_price), 1)
ref_price_value = ref_price[0].findall('./fixed_value')
self.assertEqual(ref_price_value[0].text, '-4200')

# Scaling factor
scaling_factor = cashflow[0].findall('./scaling_factor_x')
self.assertEqual(len(scaling_factor), 1)
scaling_factor_value = scaling_factor[0].findall('./fixed_value')
self.assertEqual(scaling_factor_value[0].text, '0.4')

class TestNoComponentsNode(unittest.TestCase):
class TestNoComponentsNode(HERONTestCase):

def setUp(self):
# Has no Components node
Expand Down Expand Up @@ -422,7 +405,7 @@ def test_no_comps_node(self, mock_file, mock_listdir, mock_parse):
self.assertEqual(len(components), 1)
self.assertEqual(len(components[0].findall('./Component[@name="NewComponent"]')), 1)

class TestNoComponentNodes(unittest.TestCase):
class TestNoComponentNodes(HERONTestCase):

def setUp(self):
# Has no Component nodes
Expand Down Expand Up @@ -459,7 +442,7 @@ def test_no_comp_nodes(self, mock_file, mock_listdir, mock_parse):
# Verify contents have been added
self.assertIsNotNone(component_list[0].findall('./economics/CashFlow'))

class TestMissingSubnodes(unittest.TestCase):
class TestMissingSubnodes(HERONTestCase):

def setUp(self):
# Comp0 has no economics subnode; Comp1 has no CashFlow subnode
Expand Down Expand Up @@ -518,19 +501,15 @@ def test_missing_subnodes(self, mock_listdir, mock_parse):
self.assertEqual(len(economics), 1)
cashflows = economics[0].findall('./CashFlow')
self.assertEqual(len(cashflows), 1)
self.assertEqual(cashflows[0].attrib["name"], "Component0_capex")
ref_driver = cashflows[0].find('./reference_driver/fixed_value')
self.assertEqual(ref_driver.text, "1000")
self.check_reference_driver(cashflows[0], '1000')

# Verify comp1 updated correctly
with self.subTest("cashflow node and subnodes were not added correctly"):
cashflows = comp1[0].findall('./economics/CashFlow')
self.assertEqual(len(cashflows), 1)
self.assertEqual(cashflows[0].attrib["name"], "Component1_capex")
ref_driver = cashflows[0].find('./reference_driver/fixed_value')
self.assertEqual(ref_driver.text, "2000")
self.check_reference_driver(cashflows[0], '2000')

class TestEmptyCompSetsFolder(unittest.TestCase):
class TestEmptyCompSetsFolder(HERONTestCase):
def setUp(self):
# Example of a minimal XML structure
self.heron_xml = """<HERON>
Expand Down Expand Up @@ -575,7 +554,7 @@ def test_empty_compsets_folder(self, mock_open, mock_listdir, mock_parse):
self.assertEqual(len(component_nodes), 1)
self.assertEqual(component_nodes[0].attrib['name'], 'ExistingComponent')

class TestCompSetsFolderWithBadJSON(unittest.TestCase):
class TestCompSetsFolderWithBadJSON(HERONTestCase):
def setUp(self):
# Example of a minimal XML structure
self.heron_xml = """<HERON>
Expand Down Expand Up @@ -610,7 +589,7 @@ def test_compsets_folder_bad_json(self, mock_open, mock_listdir, mock_parse):
with self.subTest("Did not respond correctly to bad component set file content"):
self.assertEqual(caught_bad_json, True)

class TestCompSetsFolderMultFiles(unittest.TestCase):
class TestCompSetsFolderMultFiles(HERONTestCase):
def setUp(self):
# Example of a minimal XML structure
self.heron_xml = """<HERON>
Expand Down Expand Up @@ -641,19 +620,20 @@ def setUp(self):
def test_compsets_folder_mult_files(self, mock_open, mock_listdir, mock_parse):
# Set up the parse mock to return an XML tree
mock_parse.return_value = self.tree
# Only the txt and json files whose names start with 'componentSet' should be opened
files_list = ['component.json', 'README', 'componentSet.csv', 'xcomponentSet.json',
'componentSet.json', 'componentSetStuff.txt',
'aFolder', 'Set.json', 'compSet.json', 'ComponentSet.json']
mock_listdir.return_value = files_list
# Only the txt and json files whose names start with 'componentSet' should be opened
acceptable_files = ['componentSet.json', 'componentSetStuff.txt']

# Call the function
result_tree = create_componentsets_in_HERON("/fake/folder", "/fake/heron_input.xml")

# Verify open function was called on correct files
for file in files_list:
# if file should have been opened
if file in ['componentSet.json', 'componentSetStuff.txt']:
if file in acceptable_files:
with self.subTest(msg="File was not opened and should have been", file = file):
# Verify file was opened
self.assertIn(call('/fake/folder/'+file), mock_open.call_args_list)
Expand Down

0 comments on commit cdfa1a4

Please sign in to comment.