mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-30 13:10:47 +00:00
Extended unit testing for roof class
This commit is contained in:
parent
66a18cf39d
commit
d5495ef775
3 changed files with 75 additions and 23 deletions
|
|
@ -3,16 +3,28 @@ from typing import Dict, Union
|
||||||
|
|
||||||
|
|
||||||
class RoofAttributes:
|
class RoofAttributes:
|
||||||
|
ROOF_TYPES = ['pitched', 'roof room', 'loft', 'flat', 'thatched', 'at rafters', 'assumed']
|
||||||
|
DWELLING_ABOVE = ["another dwelling above", "other premises above"]
|
||||||
|
|
||||||
def __init__(self, description: str):
|
def __init__(self, description: str):
|
||||||
"""
|
"""
|
||||||
:param description: Description of the roof.
|
:param description: Description of the roof.
|
||||||
"""
|
"""
|
||||||
self.description: str = description
|
|
||||||
|
self.description: str = description.lower()
|
||||||
|
|
||||||
|
if not description or not any(
|
||||||
|
rt in self.description for rt in self.ROOF_TYPES + self.DWELLING_ABOVE + ["average thermal transmittance"]
|
||||||
|
):
|
||||||
|
raise ValueError('Invalid description')
|
||||||
|
|
||||||
def process(self) -> Dict[str, Union[float, str, bool, None]]:
|
def process(self) -> Dict[str, Union[float, str, bool, None]]:
|
||||||
|
|
||||||
|
if not self.description:
|
||||||
|
raise ValueError("Description is empty")
|
||||||
|
|
||||||
result: Dict[str, Union[float, str, bool, None]] = {}
|
result: Dict[str, Union[float, str, bool, None]] = {}
|
||||||
description = self.description.lower()
|
description = self.description
|
||||||
|
|
||||||
# thermal transmittance
|
# thermal transmittance
|
||||||
match = re.search(r"average thermal transmittance (-?\d+\.\d+)\s(w/m-¦k)", description)
|
match = re.search(r"average thermal transmittance (-?\d+\.\d+)\s(w/m-¦k)", description)
|
||||||
|
|
@ -26,9 +38,8 @@ class RoofAttributes:
|
||||||
result['thermal_transmittance_unit'] = None
|
result['thermal_transmittance_unit'] = None
|
||||||
|
|
||||||
# roof type
|
# roof type
|
||||||
roof_types = ['pitched', 'roof room', 'loft', 'flat', 'thatched', 'at rafters', 'assumed']
|
|
||||||
|
|
||||||
for rt in roof_types:
|
for rt in self.ROOF_TYPES:
|
||||||
result[f'is_{rt.replace(" ", "_")}'] = rt in description
|
result[f'is_{rt.replace(" ", "_")}'] = rt in description
|
||||||
# Remove the roof type from the description
|
# Remove the roof type from the description
|
||||||
description = description.replace(rt, "")
|
description = description.replace(rt, "")
|
||||||
|
|
@ -36,7 +47,7 @@ class RoofAttributes:
|
||||||
result["has_dwelling_above"] = (
|
result["has_dwelling_above"] = (
|
||||||
"another dwelling above" in description or "other premises above" in description
|
"another dwelling above" in description or "other premises above" in description
|
||||||
)
|
)
|
||||||
for dwelling_above in ["another dwelling above", "other premises above"]:
|
for dwelling_above in self.DWELLING_ABOVE:
|
||||||
description = description.replace(dwelling_above, "")
|
description = description.replace(dwelling_above, "")
|
||||||
|
|
||||||
result["is_valid"] = "invalid" not in description
|
result["is_valid"] = "invalid" not in description
|
||||||
|
|
|
||||||
33
epc_data/tests/test_epc_clean.py
Normal file
33
epc_data/tests/test_epc_clean.py
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
import pytest
|
||||||
|
import pickle
|
||||||
|
from epc_data.EpcClean import EpcClean
|
||||||
|
from pathlib import Path
|
||||||
|
from epc_data.tests.test_data.test_roof_attributes_cases import clean_roof_test_cases
|
||||||
|
from epc_data.attributes.RoofAttributes import RoofAttributes
|
||||||
|
|
||||||
|
# For local testing
|
||||||
|
if __file__ == "<input>":
|
||||||
|
input_data_path = Path("./epc_data/tests/test_data/EpcClean_inputs.obj")
|
||||||
|
else:
|
||||||
|
current_file_path = Path(__file__)
|
||||||
|
input_data_path = current_file_path.parent / 'test_data' / 'EpcClean_inputs.obj'
|
||||||
|
|
||||||
|
|
||||||
|
class TestEpcClean:
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def load_data(path):
|
||||||
|
with open(path, "rb") as file:
|
||||||
|
return pickle.load(file)
|
||||||
|
|
||||||
|
@pytest.fixture(autouse=True)
|
||||||
|
def setup_class(self):
|
||||||
|
self.cleaner = EpcClean(self.load_data(input_data_path))
|
||||||
|
|
||||||
|
def test_clean(self):
|
||||||
|
self.cleaner.clean()
|
||||||
|
assert len(self.cleaner.cleaned["roof-description"]) == len(self.cleaner.unique_vals["roof-description"])
|
||||||
|
|
||||||
|
def test__init_empty_cleaned_obj(self):
|
||||||
|
self.cleaner._init_empty_cleaned_obj()
|
||||||
|
assert all([len(values) == 0 for values in self.cleaner.cleaned.values()])
|
||||||
|
|
@ -13,24 +13,7 @@ else:
|
||||||
input_data_path = current_file_path.parent / 'test_data' / 'EpcClean_inputs.obj'
|
input_data_path = current_file_path.parent / 'test_data' / 'EpcClean_inputs.obj'
|
||||||
|
|
||||||
|
|
||||||
class TestEpcClean:
|
class TestRoofAttributes:
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def load_data(path):
|
|
||||||
with open(path, "rb") as file:
|
|
||||||
return pickle.load(file)
|
|
||||||
|
|
||||||
@pytest.fixture(autouse=True)
|
|
||||||
def setup_class(self):
|
|
||||||
self.cleaner = EpcClean(self.load_data(input_data_path))
|
|
||||||
|
|
||||||
def test_clean(self):
|
|
||||||
self.cleaner.clean()
|
|
||||||
assert len(self.cleaner.cleaned["roof-description"]) == len(self.cleaner.unique_vals["roof-description"])
|
|
||||||
|
|
||||||
def test__init_empty_cleaned_obj(self):
|
|
||||||
self.cleaner._init_empty_cleaned_obj()
|
|
||||||
assert all([len(values) == 0 for values in self.cleaner.cleaned.values()])
|
|
||||||
|
|
||||||
def test_clean_roof(self):
|
def test_clean_roof(self):
|
||||||
result = RoofAttributes('Pitched, 270 mm loft insulation').process()
|
result = RoofAttributes('Pitched, 270 mm loft insulation').process()
|
||||||
|
|
@ -84,3 +67,28 @@ class TestEpcClean:
|
||||||
|
|
||||||
for k in expected_output:
|
for k in expected_output:
|
||||||
assert result[k] == expected_output[k]
|
assert result[k] == expected_output[k]
|
||||||
|
|
||||||
|
def test_clean_roof_invalid(self):
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
RoofAttributes('').process()
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
RoofAttributes('nonsense string').process()
|
||||||
|
|
||||||
|
def test_clean_roof_edge_cases(self):
|
||||||
|
# Insulation thickness edge case
|
||||||
|
assert RoofAttributes('Pitched, 99999 mm loft insulation').process()['insulation_thickness'] == "99999"
|
||||||
|
assert RoofAttributes('Pitched, 1 mm loft insulation').process()['insulation_thickness'] == "1"
|
||||||
|
|
||||||
|
# Special characters in the description - implement this later
|
||||||
|
# result = RoofAttributes('Pitched, **270** mm loft insulation').process()
|
||||||
|
# assert result['insulation_thickness'] == 270
|
||||||
|
|
||||||
|
def test_clean_roof_type(self):
|
||||||
|
for roof_type in ['pitched', 'roof room', 'loft', 'flat', 'thatched', 'at rafters', 'assumed']:
|
||||||
|
result = RoofAttributes(f'{roof_type}, 200 mm insulation').process()
|
||||||
|
assert result[f'is_{roof_type.replace(" ", "_")}'] is True
|
||||||
|
|
||||||
|
def test_clean_roof_thermal_transmittance(self):
|
||||||
|
result = RoofAttributes('Pitched, 200 mm insulation, average thermal transmittance 0.13 w/m-¦k').process()
|
||||||
|
assert result['thermal_transmittance'] == 0.13
|
||||||
|
assert result['thermal_transmittance_unit'] == 'w/m-¦k'
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue