mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +00:00
777 lines
41 KiB
Python
777 lines
41 KiB
Python
import pytest
|
|
from unittest.mock import Mock
|
|
from backend.Property import Property
|
|
from etl.epc.Record import EPCRecord
|
|
from recommendations.RoofRecommendations import RoofRecommendations
|
|
from recommendations.tests.test_data.materials import materials
|
|
|
|
|
|
class TestRoofRecommendations:
|
|
|
|
def test_loft_insulation_recommendation_no_insulation(self):
|
|
epc_record = EPCRecord()
|
|
epc_record.prepared_epc = {
|
|
"county": "Cambridgeshire",
|
|
}
|
|
property_instance = Property(id=0, address="fake", postcode="fake", epc_record=epc_record)
|
|
property_instance.age_band = "F"
|
|
property_instance.insulation_floor_area = 100
|
|
property_instance.roof = {
|
|
'original_description': 'Pitched, no insulation (assumed)',
|
|
'clean_description': 'Pitched, no insulation',
|
|
'thermal_transmittance': None,
|
|
'thermal_transmittance_unit': None,
|
|
'is_pitched': True, 'is_roof_room': False, 'is_loft': False, 'is_flat': False, 'is_thatched': False,
|
|
'is_at_rafters': False, 'is_assumed': True, 'has_dwelling_above': False, 'is_valid': True,
|
|
'insulation_thickness': 'none', 'roof_thermal_transmittance': None, 'roof_insulation_thickness': 'none'
|
|
}
|
|
property_instance.already_installed = []
|
|
|
|
roof_recommender = RoofRecommendations(property_instance=property_instance, materials=materials)
|
|
|
|
assert not roof_recommender.recommendations
|
|
|
|
roof_recommender.recommend(phase=0)
|
|
|
|
assert len(roof_recommender.recommendations) == 3
|
|
assert roof_recommender.recommendations[0]["parts"][0]["depth"] == 300
|
|
|
|
def test_loft_insulation_recommendation_50mm_insulation(self):
|
|
epc_record = EPCRecord()
|
|
epc_record.prepared_epc = {"county": "Kent", "roof-energy-eff": "Very Poor"}
|
|
property_instance2 = Property(id=0, address="fake", postcode="fake", epc_record=epc_record)
|
|
property_instance2.age_band = "F"
|
|
property_instance2.insulation_floor_area = 100
|
|
property_instance2.roof = {
|
|
'original_description': 'Pitched, 50mm loft insulation (assumed)',
|
|
'clean_description': 'Pitched, 50mm loft insulation',
|
|
'thermal_transmittance': None,
|
|
'thermal_transmittance_unit': None,
|
|
'is_pitched': True, 'is_roof_room': False, 'is_loft': True, 'is_flat': False, 'is_thatched': False,
|
|
'is_at_rafters': False, 'is_assumed': True, 'has_dwelling_above': False, 'is_valid': True,
|
|
'insulation_thickness': '50', 'roof_thermal_transmittance': None, 'roof_insulation_thickness': 'none'
|
|
}
|
|
property_instance2.already_installed = []
|
|
|
|
roof_recommender2 = RoofRecommendations(property_instance=property_instance2, materials=materials)
|
|
|
|
assert not roof_recommender2.recommendations
|
|
|
|
roof_recommender2.recommend(phase=0)
|
|
|
|
assert len(roof_recommender2.recommendations) == 3
|
|
|
|
assert roof_recommender2.recommendations[0]["total"] == 2100
|
|
assert roof_recommender2.recommendations[0]["new_u_value"] == 0.13
|
|
assert float(roof_recommender2.recommendations[0]["starting_u_value"]) == 0.68
|
|
assert roof_recommender2.recommendations[0]["parts"][0]["depth"] == 300
|
|
|
|
epc_record = EPCRecord()
|
|
epc_record.prepared_epc = {"county": "Greater London Authority", "roof-energy-eff": "Very Poor"}
|
|
property_instance3 = Property(id=0, address="fake", postcode="fake", epc_record=epc_record)
|
|
property_instance3.age_band = "F"
|
|
property_instance3.insulation_floor_area = 100
|
|
property_instance3.roof = {
|
|
'original_description': 'Pitched, 50mm loft insulation (assumed)',
|
|
'clean_description': 'Pitched, 50mm loft insulation',
|
|
'thermal_transmittance': None,
|
|
'thermal_transmittance_unit': None,
|
|
'is_pitched': True, 'is_roof_room': False, 'is_loft': True, 'is_flat': False, 'is_thatched': False,
|
|
'is_at_rafters': False, 'is_assumed': True, 'has_dwelling_above': False, 'is_valid': True,
|
|
'insulation_thickness': '50', 'roof_thermal_transmittance': None, 'roof_insulation_thickness': 'none'
|
|
}
|
|
property_instance3.already_installed = []
|
|
|
|
roof_recommender3 = RoofRecommendations(property_instance=property_instance3, materials=materials)
|
|
|
|
assert not roof_recommender3.recommendations
|
|
|
|
roof_recommender3.recommend(phase=0)
|
|
|
|
assert roof_recommender3.recommendations
|
|
assert len(roof_recommender3.recommendations) == 3
|
|
assert roof_recommender3.recommendations[0]["parts"][0]["depth"] == 300.0
|
|
|
|
def test_loft_insulation_recommendation_150mm_insulation(self):
|
|
epc_record = EPCRecord()
|
|
epc_record.prepared_epc = {"county": "North East Lincolnshire", "roof-energy-eff": "Good"}
|
|
property_instance4 = Property(id=0, address="fake", postcode="fake", epc_record=epc_record)
|
|
property_instance4.age_band = "F"
|
|
property_instance4.insulation_floor_area = 100
|
|
property_instance4.roof = {
|
|
'original_description': 'Pitched, 150mm loft insulation (assumed)',
|
|
'clean_description': 'Pitched, 150mm loft insulation',
|
|
'thermal_transmittance': None,
|
|
'thermal_transmittance_unit': None,
|
|
'is_pitched': True, 'is_roof_room': False, 'is_loft': True, 'is_flat': False, 'is_thatched': False,
|
|
'is_at_rafters': False, 'is_assumed': True, 'has_dwelling_above': False, 'is_valid': True,
|
|
'insulation_thickness': '150', 'roof_thermal_transmittance': None, 'roof_insulation_thickness': 'none'
|
|
}
|
|
property_instance4.already_installed = []
|
|
|
|
roof_recommender4 = RoofRecommendations(property_instance=property_instance4, materials=materials)
|
|
|
|
assert not roof_recommender4.recommendations
|
|
|
|
roof_recommender4.recommend(phase=0, default_u_values=True)
|
|
|
|
assert len(roof_recommender4.recommendations) == 3
|
|
|
|
assert roof_recommender4.recommendations[0]["total"] == 2100.0
|
|
assert float(roof_recommender4.recommendations[0]["new_u_value"]) == 0.14
|
|
assert float(roof_recommender4.recommendations[0]["starting_u_value"]) == 0.3
|
|
assert roof_recommender4.recommendations[0]["parts"][0]["depth"] == 300
|
|
|
|
epc_record = EPCRecord()
|
|
epc_record.prepared_epc = {"county": "Somerset", "roof-energy-eff": "Good"}
|
|
property_instance5 = Property(id=0, address="fake", postcode="fake", epc_record=epc_record)
|
|
property_instance5.age_band = "F"
|
|
property_instance5.insulation_floor_area = 100
|
|
property_instance5.roof = {
|
|
'original_description': 'Pitched, 150mm loft insulation (assumed)',
|
|
'clean_description': 'Pitched, 150mm loft insulation',
|
|
'thermal_transmittance': None,
|
|
'thermal_transmittance_unit': None,
|
|
'is_pitched': True, 'is_roof_room': False, 'is_loft': True, 'is_flat': False, 'is_thatched': False,
|
|
'is_at_rafters': False, 'is_assumed': True, 'has_dwelling_above': False, 'is_valid': True,
|
|
'insulation_thickness': '150', 'roof_thermal_transmittance': None, 'roof_insulation_thickness': 'none'
|
|
}
|
|
property_instance5.already_installed = []
|
|
|
|
roof_recommender5 = RoofRecommendations(property_instance=property_instance5, materials=materials)
|
|
|
|
assert not roof_recommender5.recommendations
|
|
|
|
roof_recommender5.recommend(phase=0)
|
|
|
|
assert roof_recommender5.recommendations
|
|
assert len(roof_recommender5.recommendations) == 3
|
|
assert roof_recommender5.recommendations[0]["parts"][0]["depth"] == 300
|
|
|
|
def test_loft_insulation_recommendation_270mm_insulation(self):
|
|
# We shouldn't recommend anything in this case
|
|
epc_record = EPCRecord()
|
|
epc_record.prepared_epc = {"county": "Portsmouth"}
|
|
property_instance6 = Property(id=0, address="fake", postcode="fake", epc_record=epc_record)
|
|
property_instance6.age_band = "F"
|
|
property_instance6.insulation_floor_area = 100
|
|
property_instance6.roof = {
|
|
'original_description': 'Pitched, 270mm loft insulation (assumed)',
|
|
'clean_description': 'Pitched, 270mm loft insulation',
|
|
'thermal_transmittance': None,
|
|
'thermal_transmittance_unit': None,
|
|
'is_pitched': True, 'is_roof_room': False, 'is_loft': True, 'is_flat': False, 'is_thatched': False,
|
|
'is_at_rafters': False, 'is_assumed': True, 'has_dwelling_above': False, 'is_valid': True,
|
|
'insulation_thickness': '270', 'roof_thermal_transmittance': None, 'roof_insulation_thickness': 'none'
|
|
}
|
|
property_instance6.already_installed = []
|
|
|
|
roof_recommender6 = RoofRecommendations(property_instance=property_instance6, materials=materials)
|
|
|
|
assert not roof_recommender6.recommendations
|
|
|
|
roof_recommender6.recommend(phase=0)
|
|
|
|
assert len(roof_recommender6.recommendations) == 0
|
|
|
|
def test_uninsulated_room_in_roof(self):
|
|
epc_record = EPCRecord()
|
|
epc_record.prepared_epc = {"county": "Southampton", "roof-energy-eff": "Very Poor"}
|
|
property_instance7 = Property(id=0, address="fake", postcode="fake", epc_record=epc_record)
|
|
property_instance7.age_band = "F"
|
|
property_instance7.insulation_floor_area = 100
|
|
property_instance7.roof = {
|
|
'original_description': 'Roof room(s), no insulation (assumed)',
|
|
'clean_description': 'Roof room(s), no insulation',
|
|
'thermal_transmittance': None, 'thermal_transmittance_unit': None, 'is_pitched': False,
|
|
'is_roof_room': True, 'is_loft': False, 'is_flat': False, 'is_thatched': False, 'is_at_rafters': False,
|
|
'is_assumed': True, 'has_dwelling_above': False, 'is_valid': True, 'insulation_thickness': 'none'
|
|
}
|
|
property_instance7.already_installed = []
|
|
|
|
property_instance7.pitched_roof_area = 110
|
|
|
|
roof_recommender7 = RoofRecommendations(property_instance=property_instance7, materials=materials)
|
|
|
|
assert not roof_recommender7.recommendations
|
|
|
|
roof_recommender7.recommend(phase=0)
|
|
|
|
assert len(roof_recommender7.recommendations) == 1
|
|
assert roof_recommender7.recommendations[0]["new_u_value"] == 0.18
|
|
assert roof_recommender7.recommendations[0]["starting_u_value"] == 0.8
|
|
assert roof_recommender7.recommendations[0]["description"] == "Insulate room in roof at rafters and re-decorate"
|
|
|
|
def test_ceiling_insulated_room_in_roof(self):
|
|
epc_record = EPCRecord()
|
|
epc_record.prepared_epc = {"county": "Southampton", "roof-energy-eff": "Very Poor"}
|
|
property_instance8 = Property(id=8, address="fake", postcode="fake", epc_record=epc_record)
|
|
property_instance8.age_band = "F"
|
|
property_instance8.insulation_floor_area = 100
|
|
property_instance8.roof = {
|
|
'original_description': 'Roof room(s), ceiling insulated',
|
|
'clean_description': 'Roof room(s), ceiling insulated',
|
|
'thermal_transmittance': None, 'thermal_transmittance_unit': None, 'is_pitched': False,
|
|
'is_roof_room': True, 'is_loft': False, 'is_flat': False, 'is_thatched': False,
|
|
'is_at_rafters': False,
|
|
'is_assumed': False, 'has_dwelling_above': False, 'is_valid': True,
|
|
'insulation_thickness': 'average'
|
|
}
|
|
property_instance8.already_installed = []
|
|
|
|
property_instance8.pitched_roof_area = 110
|
|
|
|
roof_recommender8 = RoofRecommendations(property_instance=property_instance8, materials=materials)
|
|
|
|
assert not roof_recommender8.recommendations
|
|
|
|
roof_recommender8.recommend(phase=0)
|
|
|
|
# No recommendations in this case
|
|
assert not roof_recommender8.recommendations
|
|
|
|
def test_insulated_room_in_roof(self):
|
|
epc_record = EPCRecord()
|
|
epc_record.prepared_epc = {"county": "Southampton", "roof-energy-eff": "Very Poor"}
|
|
property_instance9 = Property(id=9, address="fake", postcode="fake", epc_record=epc_record)
|
|
property_instance9.age_band = "F"
|
|
property_instance9.insulation_floor_area = 100
|
|
property_instance9.roof = {
|
|
'original_description': 'Roof room(s), insulated (assumed)',
|
|
'clean_description': 'Roof room(s), insulated',
|
|
'thermal_transmittance': None, 'thermal_transmittance_unit': None, 'is_pitched': False,
|
|
'is_roof_room': True, 'is_loft': False, 'is_flat': False, 'is_thatched': False, 'is_at_rafters': False,
|
|
'is_assumed': True, 'has_dwelling_above': False, 'is_valid': True, 'insulation_thickness': 'average'
|
|
}
|
|
property_instance9.already_installed = []
|
|
|
|
property_instance9.pitched_roof_area = 110
|
|
property_instance9.data = {"county": "Rutland"}
|
|
|
|
roof_recommender9 = RoofRecommendations(property_instance=property_instance9, materials=materials)
|
|
|
|
assert not roof_recommender9.recommendations
|
|
|
|
roof_recommender9.recommend(phase=0)
|
|
|
|
# No recommendations in this case
|
|
assert not roof_recommender9.recommendations
|
|
|
|
def test_limited_insulated_room_in_roof(self):
|
|
epc_record = EPCRecord()
|
|
epc_record.prepared_epc = {"county": "Westmorland", "roof-energy-eff": "Poor"}
|
|
property_instance10 = Property(id=10, address="fake", postcode="fake", epc_record=epc_record)
|
|
property_instance10.age_band = "F"
|
|
property_instance10.insulation_floor_area = 100
|
|
property_instance10.roof = {
|
|
'original_description': 'Roof room(s), limited insulation (assumed)',
|
|
'clean_description': 'Roof room(s), limited insulation',
|
|
'thermal_transmittance': None, 'thermal_transmittance_unit': None, 'is_pitched': False,
|
|
'is_roof_room': True, 'is_loft': False, 'is_flat': False, 'is_thatched': False, 'is_at_rafters': False,
|
|
'is_assumed': True, 'has_dwelling_above': False, 'is_valid': True,
|
|
'insulation_thickness': 'below average'
|
|
}
|
|
property_instance10.already_installed = []
|
|
|
|
property_instance10.pitched_roof_area = 110
|
|
|
|
roof_recommender10 = RoofRecommendations(property_instance=property_instance10, materials=materials)
|
|
|
|
assert not roof_recommender10.recommendations
|
|
|
|
roof_recommender10.recommend(phase=0)
|
|
|
|
assert len(roof_recommender10.recommendations) == 1
|
|
|
|
assert roof_recommender10.recommendations[0]["new_u_value"] == 0.17
|
|
|
|
assert roof_recommender10.recommendations[0]["starting_u_value"] == 0.68
|
|
|
|
assert (roof_recommender10.recommendations[0]["description"] ==
|
|
'Insulate room in roof at rafters and re-decorate')
|
|
|
|
def test_flat_no_insulation(self):
|
|
epc_record = EPCRecord()
|
|
epc_record.prepared_epc = {"county": "Swindon"}
|
|
property_instance11 = Property(id=11, address="fake", postcode="fake", epc_record=epc_record)
|
|
property_instance11.age_band = "D"
|
|
property_instance11.insulation_floor_area = 33.5
|
|
property_instance11.perimeter = 24
|
|
property_instance11.roof = {
|
|
'original_description': 'Flat, no insulation (assumed)',
|
|
'clean_description': 'Flat, no insulation',
|
|
'thermal_transmittance': None, 'thermal_transmittance_unit': None, 'is_pitched': False,
|
|
'is_roof_room': False, 'is_loft': False, 'is_flat': True, 'is_thatched': False, 'is_at_rafters': False,
|
|
'is_assumed': True, 'has_dwelling_above': False, 'is_valid': True, 'insulation_thickness': 'none'
|
|
}
|
|
property_instance11.already_installed = []
|
|
|
|
roof_recommender11 = RoofRecommendations(property_instance=property_instance11, materials=materials)
|
|
|
|
assert not roof_recommender11.recommendations
|
|
|
|
roof_recommender11.recommend(phase=0)
|
|
|
|
assert len(roof_recommender11.recommendations) == 1
|
|
|
|
assert roof_recommender11.recommendations[0]["parts"][0]["depth"] == 150
|
|
assert roof_recommender11.recommendations[0]["total"] == 6532.5
|
|
assert roof_recommender11.recommendations[0]["new_u_value"] == 0.14
|
|
assert roof_recommender11.recommendations[0]["starting_u_value"] == 2.3
|
|
assert roof_recommender11.recommendations[0]["description"] == \
|
|
"Insulate the home's flat roof with 150mm of Ecotherm Eco-Versal General Purpose Insulation Board"
|
|
|
|
def test_flat_insulated(self):
|
|
epc_record = EPCRecord()
|
|
epc_record.prepared_epc = {"county": "Thurrock"}
|
|
property_instance12 = Property(id=12, address="fake", postcode="fake", epc_record=epc_record)
|
|
property_instance12.age_band = "D"
|
|
property_instance12.insulation_floor_area = 40
|
|
property_instance12.perimeter = 30
|
|
|
|
property_instance12.roof = {
|
|
'original_description': 'Flat, insulated (assumed)',
|
|
'clean_description': 'Flat, insulated',
|
|
'thermal_transmittance': None, 'thermal_transmittance_unit': None, 'is_pitched': False,
|
|
'is_roof_room': False,
|
|
'is_loft': False, 'is_flat': True, 'is_thatched': False, 'is_at_rafters': False, 'is_assumed': True,
|
|
'has_dwelling_above': False, 'is_valid': True, 'insulation_thickness': 'average'
|
|
}
|
|
property_instance12.already_installed = []
|
|
|
|
roof_recommender12 = RoofRecommendations(property_instance=property_instance12, materials=materials)
|
|
|
|
assert not roof_recommender12.recommendations
|
|
|
|
roof_recommender12.recommend(phase=0)
|
|
|
|
assert not roof_recommender12.recommendations
|
|
|
|
def test_flat_limited_insulation(self):
|
|
epc_record = EPCRecord()
|
|
epc_record.prepared_epc = {"county": "Tyne and Wear"}
|
|
property_instance13 = Property(id=12, address="fake", postcode="fake", epc_record=epc_record)
|
|
property_instance13.age_band = "D"
|
|
property_instance13.insulation_floor_area = 40
|
|
property_instance13.perimeter = 40
|
|
property_instance13.roof = {
|
|
'original_description': 'Flat, limited insulation (assumed)',
|
|
'clean_description': 'Flat, limited insulation',
|
|
'thermal_transmittance': None, 'thermal_transmittance_unit': None, 'is_pitched': False,
|
|
'is_roof_room': False,
|
|
'is_loft': False, 'is_flat': True, 'is_thatched': False, 'is_at_rafters': False, 'is_assumed': True,
|
|
'has_dwelling_above': False, 'is_valid': True, 'insulation_thickness': 'below average'
|
|
}
|
|
property_instance13.already_installed = []
|
|
|
|
roof_recommender13 = RoofRecommendations(property_instance=property_instance13, materials=materials)
|
|
|
|
assert not roof_recommender13.recommendations
|
|
|
|
roof_recommender13.recommend(phase=0)
|
|
|
|
assert len(roof_recommender13.recommendations) == 1
|
|
|
|
assert roof_recommender13.recommendations[0]["parts"][0]["depth"] == 150
|
|
|
|
assert roof_recommender13.recommendations[0]["total"] == 7800
|
|
assert roof_recommender13.recommendations[0]["new_u_value"] == 0.14
|
|
assert roof_recommender13.recommendations[0]["starting_u_value"] == 2.3
|
|
|
|
assert roof_recommender13.recommendations[0]["description"] == \
|
|
"Insulate the home's flat roof with 150mm of Ecotherm Eco-Versal General Purpose Insulation Board"
|
|
|
|
def test_property_above(self):
|
|
epc_record = EPCRecord()
|
|
epc_record.prepared_epc = {"county": "Suffolk"}
|
|
property_instance14 = Property(id=0, address="fake", postcode="fake", epc_record=epc_record)
|
|
property_instance14.age_band = "F"
|
|
property_instance14.insulation_floor_area = 100
|
|
property_instance14.roof = {
|
|
'original_description': '(other premises above)',
|
|
'clean_description': '(other premises above)', 'thermal_transmittance': 0,
|
|
'thermal_transmittance_unit': 'w/m-¦k', 'is_pitched': False, 'is_roof_room': False,
|
|
'is_loft': False, 'is_flat': False, 'is_thatched': False, 'is_at_rafters': False,
|
|
'is_assumed': False, 'has_dwelling_above': True, 'is_valid': True,
|
|
'insulation_thickness': None
|
|
}
|
|
property_instance14.already_installed = []
|
|
|
|
roof_recommender14 = RoofRecommendations(property_instance=property_instance14, materials=materials)
|
|
|
|
assert not roof_recommender14.recommendations
|
|
|
|
roof_recommender14.recommend(phase=0)
|
|
|
|
assert not roof_recommender14.recommendations
|
|
|
|
# ~~~~~~~~~~~~ Sloping Ceiling Insulation ~~~~~~~~~~~~
|
|
@pytest.mark.parametrize(
|
|
"roof, has_sloping_ceiling_recommendation, primary_roof_looks_sloped, insulation_thickness, "
|
|
"has_loft_insulation_recommendation, expected_result",
|
|
[
|
|
(
|
|
{
|
|
'original_description': 'Pitched, no insulation',
|
|
'thermal_transmittance': None,
|
|
'thermal_transmittance_unit': None,
|
|
'is_pitched': True,
|
|
'is_roof_room': False,
|
|
'is_loft': False,
|
|
'is_flat': False,
|
|
'is_thatched': False,
|
|
'is_at_rafters': False,
|
|
'is_assumed': False,
|
|
'has_dwelling_above': False,
|
|
'is_valid': True,
|
|
'insulation_thickness': 'none'
|
|
},
|
|
True,
|
|
True,
|
|
"none",
|
|
False,
|
|
True,
|
|
),
|
|
(
|
|
{
|
|
'original_description': 'Pitched, insulated (assumed)', 'clean_description': 'Pitched, insulated',
|
|
'thermal_transmittance': None, 'thermal_transmittance_unit': None, 'is_pitched': True,
|
|
'is_roof_room': False, 'is_loft': False, 'is_flat': False, 'is_thatched': False,
|
|
'is_at_rafters': False, 'is_assumed': True, 'has_dwelling_above': False, 'is_valid': True,
|
|
'insulation_thickness': 'average'
|
|
},
|
|
False,
|
|
False,
|
|
"average",
|
|
False,
|
|
False
|
|
)
|
|
]
|
|
)
|
|
def test_is_sloping_ceiling_appropriate(
|
|
self, roof, has_sloping_ceiling_recommendation, primary_roof_looks_sloped,
|
|
insulation_thickness, has_loft_insulation_recommendation, expected_result
|
|
):
|
|
assert RoofRecommendations.is_sloping_ceiling_appropriate(
|
|
is_flat=roof["is_flat"],
|
|
is_pitched=roof["is_pitched"],
|
|
is_loft=roof["is_loft"],
|
|
is_assumed=roof["is_assumed"],
|
|
has_sloping_ceiling_recommendation=has_sloping_ceiling_recommendation,
|
|
primary_roof_looks_sloped=primary_roof_looks_sloped,
|
|
insulation_thickness=insulation_thickness,
|
|
has_loft_insulation_recommendation=has_loft_insulation_recommendation
|
|
) == expected_result
|
|
|
|
def test_sloping_ceiling_pitched_no_insulation(self):
|
|
property_instance = Mock(
|
|
id=0,
|
|
roof={
|
|
'original_description': 'Pitched, no insulation', 'clean_description': 'Pitched, no insulation',
|
|
'thermal_transmittance': None, 'thermal_transmittance_unit': None, 'is_pitched': True,
|
|
'is_roof_room': False, 'is_loft': False, 'is_flat': False, 'is_thatched': False,
|
|
'is_at_rafters': False, 'is_assumed': False, 'has_dwelling_above': False, 'is_valid': True,
|
|
'insulation_thickness': 'none'
|
|
},
|
|
roof_area=64.085,
|
|
data={"county": None, "local-authority-label": "Manchester"},
|
|
age_band="D",
|
|
already_installed=[],
|
|
non_invasive_recommendations=[
|
|
{'type': 'flat_roof_insulation', 'sap_points': 9, 'survey': True},
|
|
{'type': 'sloping_ceiling_insulation', 'sap_points': 9, 'survey': True},
|
|
{'type': 'cavity_wall_insulation', 'sap_points': 6, 'survey': True},
|
|
{'type': 'suspended_floor_insulation', 'sap_points': 2, 'survey': True},
|
|
{'type': 'roomstat_programmer_trvs', 'sap_points': 3, 'survey': True},
|
|
{'type': 'time_temperature_zone_control', 'sap_points': 3, 'survey': True},
|
|
{'type': 'solar_pv', 'sap_points': 5, 'survey': True, 'suitable': True}
|
|
],
|
|
find_my_epc_components=[
|
|
{'component_name': 'Wall', 'description': 'Solid brick, as built, no insulation (assumed)',
|
|
'efficiency': 'Very poor', 'appearance_index': 0},
|
|
{'component_name': 'Roof', 'description': 'Pitched, no insulation', 'efficiency': 'Very poor',
|
|
'appearance_index': 0},
|
|
{'component_name': 'Roof', 'description': 'Pitched, limited insulation', 'efficiency': 'Very poor',
|
|
'appearance_index': 1},
|
|
{'component_name': 'Window', 'description': 'Some multiple glazing', 'efficiency': 'Very poor',
|
|
'appearance_index': 0},
|
|
{'component_name': 'Main heating', 'description': 'Boiler and radiators, mains gas',
|
|
'efficiency': 'Good', 'appearance_index': 0},
|
|
{'component_name': 'Main heating control', 'description': 'Programmer, room thermostat and TRVs',
|
|
'efficiency': 'Good', 'appearance_index': 0},
|
|
{'component_name': 'Hot water', 'description': 'From main system', 'efficiency': 'Good',
|
|
'appearance_index': 0},
|
|
{'component_name': 'Lighting', 'description': 'Low energy lighting in 28% of fixed outlets',
|
|
'efficiency': 'Average', 'appearance_index': 0},
|
|
{'component_name': 'Floor', 'description': 'Solid, no insulation (assumed)', 'efficiency': 'N/A',
|
|
'appearance_index': 0},
|
|
{'component_name': 'Secondary heating', 'description': 'None', 'efficiency': 'N/A',
|
|
'appearance_index': 0}
|
|
]
|
|
|
|
)
|
|
|
|
roof_recommender = RoofRecommendations(property_instance=property_instance, materials=[])
|
|
assert not roof_recommender.recommendations
|
|
|
|
roof_recommender.recommend(phase=0)
|
|
assert len(roof_recommender.recommendations) == 1
|
|
|
|
assert roof_recommender.recommendations[0]["type"] == "sloping_ceiling_insulation"
|
|
assert roof_recommender.recommendations[0]["measure_type"] == "sloping_ceiling_insulation"
|
|
assert (
|
|
roof_recommender.recommendations[0]["description"] ==
|
|
"Insulate sloping ceilings at the rafters and re-decorate"
|
|
)
|
|
assert roof_recommender.recommendations[0]["simulation_config"] == {
|
|
'roof_insulation_thickness_ending': 'average',
|
|
'roof_thermal_transmittance_ending': 0.5,
|
|
'roof_energy_eff_ending': 'Average'
|
|
}
|
|
|
|
assert roof_recommender.recommendations[0]["description_simulation"] == {
|
|
'roof-description': 'Pitched, insulated', 'roof-energy-eff': 'Average'
|
|
}
|
|
|
|
def test_ambiguous_sloping_ceiling_or_loft(self):
|
|
# In this case, we actually expect loft insulation to be recommended
|
|
property_instance = Mock(
|
|
id=0,
|
|
roof={
|
|
# Roof looks like it could be a sloping ceiling but it's actually a loft
|
|
'original_description': 'Pitched, no insulation', 'clean_description': 'Pitched, no insulation',
|
|
'thermal_transmittance': None, 'thermal_transmittance_unit': None, 'is_pitched': True,
|
|
'is_roof_room': False, 'is_loft': False, 'is_flat': False, 'is_thatched': False,
|
|
'is_at_rafters': False, 'is_assumed': False, 'has_dwelling_above': False, 'is_valid': True,
|
|
'insulation_thickness': 'none'
|
|
},
|
|
roof_area=197.748,
|
|
data={"county": None, "local-authority-label": "Manchester"},
|
|
already_installed=[],
|
|
find_my_epc_components=[
|
|
{'component_name': 'Wall', 'description': 'Solid brick, as built, no insulation (assumed)',
|
|
'efficiency': 'Very poor', 'appearance_index': 0},
|
|
{'component_name': 'Roof', 'description': 'Pitched, no insulation', 'efficiency': 'Very poor',
|
|
'appearance_index': 0},
|
|
{'component_name': 'Roof', 'description': 'Pitched, limited insulation', 'efficiency': 'Very poor',
|
|
'appearance_index': 1},
|
|
{'component_name': 'Window', 'description': 'Some multiple glazing', 'efficiency': 'Very poor',
|
|
'appearance_index': 0},
|
|
{'component_name': 'Main heating', 'description': 'Boiler and radiators, mains gas',
|
|
'efficiency': 'Good', 'appearance_index': 0},
|
|
{'component_name': 'Main heating control', 'description': 'Programmer, room thermostat and TRVs',
|
|
'efficiency': 'Good', 'appearance_index': 0},
|
|
{'component_name': 'Hot water', 'description': 'From main system', 'efficiency': 'Good',
|
|
'appearance_index': 0},
|
|
{'component_name': 'Lighting', 'description': 'Low energy lighting in 28% of fixed outlets',
|
|
'efficiency': 'Average', 'appearance_index': 0},
|
|
{'component_name': 'Floor', 'description': 'Solid, no insulation (assumed)', 'efficiency': 'N/A',
|
|
'appearance_index': 0},
|
|
{'component_name': 'Secondary heating', 'description': 'None', 'efficiency': 'N/A',
|
|
'appearance_index': 0}
|
|
],
|
|
age_band="B",
|
|
non_invasive_recommendations=[
|
|
{'type': 'loft_insulation', 'sap_points': 3, 'survey': True},
|
|
{'type': 'flat_roof_insulation', 'sap_points': 2, 'survey': True},
|
|
{'type': 'sloping_ceiling_insulation', 'sap_points': 2, 'survey': True},
|
|
{'type': 'internal_wall_insulation', 'sap_points': 9, 'survey': True},
|
|
{'type': 'draught_proofing', 'sap_points': 1, 'survey': True},
|
|
{'type': 'low_energy_lighting', 'sap_points': 1, 'survey': True},
|
|
{'type': 'solar_water_heating', 'sap_points': 1, 'survey': True},
|
|
{'type': 'double_glazing', 'sap_points': 3, 'survey': True},
|
|
{'type': 'solar_pv', 'sap_points': 4, 'survey': True, 'suitable': True}
|
|
],
|
|
insulation_floor_area=162
|
|
)
|
|
|
|
roof_recommender = RoofRecommendations(property_instance=property_instance, materials=materials)
|
|
assert not roof_recommender.recommendations
|
|
|
|
roof_recommender.recommend(phase=0)
|
|
assert len(roof_recommender.recommendations) == 3
|
|
|
|
# Should all be loft insulation recommendations
|
|
assert all(
|
|
rec["type"] == "loft_insulation" for rec in roof_recommender.recommendations
|
|
)
|
|
|
|
def test_no_access_pitched_roof_assumed(self):
|
|
"""
|
|
In this case, the roof will have been surveyed as pitched, but the surveyor won't
|
|
have gotten access to the property to check the insulation. Therefore, we
|
|
recommend loft insulation. We assume that the roof is a locked off loft
|
|
:return:
|
|
"""
|
|
|
|
property_instance = Mock(
|
|
id=0,
|
|
roof={
|
|
'original_description': 'Pitched, limited insulation (assumed)',
|
|
'clean_description': 'Pitched, limited insulation', 'thermal_transmittance': None,
|
|
'thermal_transmittance_unit': None, 'is_pitched': True, 'is_roof_room': False, 'is_loft': False,
|
|
'is_flat': False, 'is_thatched': False, 'is_at_rafters': False, 'is_assumed': True,
|
|
'has_dwelling_above': False, 'is_valid': True, 'insulation_thickness': 'below average'
|
|
},
|
|
roof_area=73.24,
|
|
data={"county": None, "local-authority-label": "Manchester"},
|
|
already_installed=[],
|
|
find_my_epc_components=[
|
|
{'component_name': 'Wall', 'description': 'Solid brick, as built, no insulation (assumed)',
|
|
'efficiency': 'Very poor', 'appearance_index': 0},
|
|
{'component_name': 'Wall', 'description': 'System built, as built, no insulation (assumed)',
|
|
'efficiency': 'Poor', 'appearance_index': 1},
|
|
{'component_name': 'Wall', 'description': 'Cavity wall, filled cavity', 'efficiency': 'Average',
|
|
'appearance_index': 2},
|
|
{'component_name': 'Roof', 'description': 'Pitched, limited insulation (assumed)',
|
|
'efficiency': 'Very poor', 'appearance_index': 0},
|
|
{'component_name': 'Window', 'description': 'Fully double glazed', 'efficiency': 'Average',
|
|
'appearance_index': 0},
|
|
{'component_name': 'Main heating', 'description': 'Boiler and radiators, mains gas',
|
|
'efficiency': 'Good', 'appearance_index': 0},
|
|
{'component_name': 'Main heating control', 'description': 'Programmer and room thermostat',
|
|
'efficiency': 'Average', 'appearance_index': 0},
|
|
{'component_name': 'Hot water', 'description': 'From main system', 'efficiency': 'Good',
|
|
'appearance_index': 0},
|
|
{'component_name': 'Lighting', 'description': 'Low energy lighting in 75% of fixed outlets',
|
|
'efficiency': 'Very good', 'appearance_index': 0},
|
|
{'component_name': 'Roof', 'description': '(another dwelling above)', 'efficiency': 'N/A',
|
|
'appearance_index': 1},
|
|
{'component_name': 'Floor', 'description': 'Suspended, no insulation (assumed)', 'efficiency': 'N/A',
|
|
'appearance_index': 0},
|
|
{'component_name': 'Floor', 'description': 'Solid, no insulation (assumed)', 'efficiency': 'N/A',
|
|
'appearance_index': 1},
|
|
{'component_name': 'Secondary heating', 'description': 'None', 'efficiency': 'N/A',
|
|
'appearance_index': 0}
|
|
],
|
|
age_band="B",
|
|
non_invasive_recommendations=[
|
|
{'type': 'internal_wall_insulation', 'sap_points': 2, 'survey': True},
|
|
{'type': 'suspended_floor_insulation', 'sap_points': 2, 'survey': True},
|
|
{'type': 'solid_floor_insulation', 'sap_points': 1, 'survey': True},
|
|
{'type': 'low_energy_lighting', 'sap_points': 0, 'survey': True}
|
|
],
|
|
insulation_floor_area=60
|
|
)
|
|
|
|
roof_recommender = RoofRecommendations(property_instance=property_instance, materials=materials)
|
|
assert not roof_recommender.recommendations
|
|
|
|
roof_recommender.recommend(phase=0)
|
|
assert len(roof_recommender.recommendations) == 3
|
|
|
|
# Should all be loft insulation recommendations
|
|
assert all(
|
|
rec["type"] == "loft_insulation" for rec in roof_recommender.recommendations
|
|
)
|
|
|
|
def test_traditional_loft_insulation(self):
|
|
property_instance = Mock(
|
|
id=0,
|
|
roof={
|
|
'original_description': 'Pitched, no insulation', 'clean_description': 'Pitched, no insulation',
|
|
'thermal_transmittance': None, 'thermal_transmittance_unit': None, 'is_pitched': True,
|
|
'is_roof_room': False, 'is_loft': False, 'is_flat': False, 'is_thatched': False,
|
|
'is_at_rafters': False, 'is_assumed': False, 'has_dwelling_above': False, 'is_valid': True,
|
|
'insulation_thickness': 'none'
|
|
},
|
|
roof_area=48.82666666666667,
|
|
data={"county": None, "local-authority-label": "Manchester"},
|
|
already_installed=[],
|
|
find_my_epc_components=[
|
|
{'component_name': 'Wall', 'description': 'Cavity wall, filled cavity', 'efficiency': 'Good',
|
|
'appearance_index': 0},
|
|
{'component_name': 'Roof', 'description': 'Pitched, no insulation', 'efficiency': 'Very poor',
|
|
'appearance_index': 0},
|
|
{'component_name': 'Window', 'description': 'Fully double glazed', 'efficiency': 'Good',
|
|
'appearance_index': 0},
|
|
{'component_name': 'Main heating', 'description': 'Boiler and radiators, mains gas',
|
|
'efficiency': 'Good', 'appearance_index': 0},
|
|
{'component_name': 'Main heating control', 'description': 'TRVs and bypass', 'efficiency': 'Average',
|
|
'appearance_index': 0},
|
|
{'component_name': 'Hot water', 'description': 'From main system', 'efficiency': 'Good',
|
|
'appearance_index': 0},
|
|
{'component_name': 'Lighting', 'description': 'Low energy lighting in all fixed outlets',
|
|
'efficiency': 'Very good', 'appearance_index': 0},
|
|
{'component_name': 'Floor', 'description': 'Solid, no insulation (assumed)', 'efficiency': 'N/A',
|
|
'appearance_index': 0},
|
|
{'component_name': 'Secondary heating', 'description': 'Room heaters, electric', 'efficiency': 'N/A',
|
|
'appearance_index': 0}
|
|
],
|
|
age_band="F",
|
|
non_invasive_recommendations=[
|
|
{'type': 'loft_insulation', 'sap_points': 9, 'survey': True},
|
|
{'type': 'solid_floor_insulation', 'sap_points': 2, 'survey': True},
|
|
{'type': 'solar_water_heating', 'sap_points': 1, 'survey': True},
|
|
{'type': 'solar_pv', 'sap_points': 11, 'survey': True, 'suitable': True}
|
|
],
|
|
insulation_floor_area=40.0
|
|
)
|
|
|
|
roof_recommender = RoofRecommendations(property_instance=property_instance, materials=materials)
|
|
assert not roof_recommender.recommendations
|
|
|
|
roof_recommender.recommend(0)
|
|
assert len(roof_recommender.recommendations) == 3
|
|
# should all be loft insulation recommendations
|
|
assert all(rec["type"] == "loft_insulation" for rec in roof_recommender.recommendations)
|
|
|
|
def sloping_ceiling_limited_insulation(self):
|
|
property_instance = Mock(
|
|
id=0,
|
|
roof={
|
|
"original_description": 'Pitched, limited insulation (assumed)',
|
|
'clean_description': 'Pitched, limited insulation',
|
|
'thermal_transmittance': None, 'thermal_transmittance_unit': None, 'is_pitched': True,
|
|
'is_roof_room': False, 'is_loft': False, 'is_flat': False, 'is_thatched': False, 'is_at_rafters': False,
|
|
'is_assumed': True, 'has_dwelling_above': False, 'is_valid': True,
|
|
'insulation_thickness': 'below average'
|
|
},
|
|
roof_area=35,
|
|
data={"county": None, "local-authority-label": "Manchester"},
|
|
already_installed=[],
|
|
find_my_epc_components=[
|
|
{'component_name': 'Wall', 'description': 'Cavity wall, as built, no insulation (assumed)',
|
|
'efficiency': 'poor', 'appearance_index': 0},
|
|
{'component_name': 'Roof', 'description': 'Pitched, limited insulation (assumed)',
|
|
'efficiency': 'Very poor', 'appearance_index': 0},
|
|
{'component_name': 'Window', 'description': 'Fully double glazed', 'efficiency': 'Average',
|
|
'appearance_index': 0},
|
|
{'component_name': 'Main heating', 'description': 'Boiler and radiators, mains gas',
|
|
'efficiency': 'Good', 'appearance_index': 0},
|
|
{'component_name': 'Main heating control', 'description': 'TRVs and bypass',
|
|
'efficiency': 'Average', 'appearance_index': 0},
|
|
{'component_name': 'Hot water', 'description': 'From main system', 'efficiency': 'Good',
|
|
'appearance_index': 0},
|
|
{'component_name': 'Lighting', 'description': 'Low energy lighting in all fixed outlets',
|
|
'efficiency': 'Very good', 'appearance_index': 0},
|
|
{'component_name': 'Floor', 'description': '(another dwelling below)', 'efficiency': 'N/A',
|
|
'appearance_index': 0},
|
|
{'component_name': 'Secondary heating', 'description': 'None', 'efficiency': 'N/A',
|
|
'appearance_index': 0}
|
|
],
|
|
age_band="B",
|
|
non_invasive_recommendations=[
|
|
{'type': 'sloping_ceiling_insulation', 'sap_points': 2, 'survey': True},
|
|
{'type': 'flat_roof_insulation', 'sap_points': 2, 'survey': True},
|
|
],
|
|
)
|
|
|
|
# We expect a sloping ceiling insulation recommendation
|
|
roof_recommender = RoofRecommendations(property_instance=property_instance, materials=materials)
|
|
assert not roof_recommender.recommendations
|
|
|
|
roof_recommender.recommend(phase=0)
|
|
assert len(roof_recommender.recommendations) == 1
|
|
assert roof_recommender.recommendations[0]["type"] == "sloping_ceiling_insulation"
|
|
assert roof_recommender.recommendations[0]["measure_type"] == "sloping_ceiling_insulation"
|
|
assert roof_recommender.recommendations[0]["description"] == \
|
|
"Insulate sloping ceilings at the rafters and re-decorate"
|
|
assert roof_recommender.recommendations[0]["simulation_config"] == {
|
|
'roof_insulation_thickness_ending': 'average',
|
|
'roof_thermal_transmittance_ending': 0.5,
|
|
'roof_energy_eff_ending': 'Average'
|
|
}
|
|
assert roof_recommender.recommendations[0]["description_simulation"] == {
|
|
'roof-description': 'Pitched, insulated', 'roof-energy-eff': 'Average'
|
|
}
|