Model/backend/tests/test_property.py
Khalim Conn-Kowlessar 0da24a955c fixed property tests
2023-10-09 06:33:28 +08:00

308 lines
13 KiB
Python

import pytest
from unittest.mock import Mock
from epc_api.client import EpcClient
from backend.Property import Property
from etl.epc_clean.EpcClean import EpcClean
# Define some test data
mock_epc_response = {
"rows": [
{
"lmk-key": 1,
"uprn": 1,
"number-habitable-rooms": 5,
"property-type": "House",
"inspection-date": "2023-06-01",
"some-other-key": "some-value",
"roof-description": "Roof Description",
"walls-description": "Walls Description",
"windows-description": "Windows Description",
"mainheat-description": "Main Heating Description",
"hotwater-description": "Hot Water Description",
"transaction-type": "rental",
"lighting-description": "Good Lighting Efficiency",
"energy-consumption-current": "50",
"co2-emissions-current": "123",
"mechanical-ventilation": "natural",
'photo-supply': 0,
"solar-water-heating-flag": "N",
"wind-turbine-count": 0,
"extension-count": 0,
"heat-loss-corridor": "no corridor",
"unheated-corridor-length": 0,
"mains-gas-flag": "Y",
"floor-height": 2.5,
"total-floor-area": 100,
"construction-age-band": "England and Wales: 1967-1975"
},
{
"lmk-key": 2,
"uprn": 2,
"number-habitable-rooms": 5,
"property-type": "House",
"inspection-date": "2023-05-01",
"some-other-key": "some-other-value",
"roof-description": "Roof Description",
"walls-description": "Walls Description",
"windows-description": "Windows Description",
"mainheat-description": "Main Heating Description",
"hotwater-description": "Hot Water Description",
"transaction-type": "rental",
"lighting-description": "Good Lighting Efficiency",
"energy-consumption-current": "50",
"co2-emissions-current": "123",
"mechanical-ventilation": "natural",
'photo-supply': 0,
"solar-water-heating-flag": "N",
"wind-turbine-count": 0,
"extension-count": 0,
"heat-loss-corridor": "no corridor",
"unheated-corridor-length": 0,
"mains-gas-flag": "Y",
"floor-height": 2.5,
"total-floor-area": 100,
"construction-age-band": "England and Wales: 1967-1975"
}
]
}
mock_epc_response_dupe = {
'rows': [
{
"lmk-key": 1,
"uprn": 1,
"number-habitable-rooms": 5,
"property-type": "House",
'inspection-date': '2023-06-01', 'some-other-key': 'some-value', 'roof-description': 'Roof Description',
'walls-description': 'Walls Description', 'windows-description': 'Windows Description',
'mainheat-description': 'Main Heating Description', 'hotwater-description': 'Hot Water Description',
"transaction-type": "rental",
"lighting-description": "Good Lighting Efficiency",
"energy-consumption-current": "50",
"co2-emissions-current": "123",
"mechanical-ventilation": "natural",
'photo-supply': 0,
"solar-water-heating-flag": "N",
"wind-turbine-count": 0,
"extension-count": 0,
"heat-loss-corridor": "no corridor",
"unheated-corridor-length": 0,
"mains-gas-flag": "Y",
"floor-height": 2.5,
"total-floor-area": 100,
"construction-age-band": "England and Wales: 1967-1975"
},
{
"lmk-key": 2,
"uprn": 2,
"number-habitable-rooms": 5,
"property-type": "House",
'inspection-date': '2023-05-01', 'some-other-key': 'some-other-value',
'roof-description': 'Roof Description', 'walls-description': 'Walls Description',
'windows-description': 'Windows Description', 'mainheat-description': 'Main Heating Description',
'hotwater-description': 'Hot Water Description',
"transaction-type": "rental",
"lighting-description": "Good Lighting Efficiency",
"energy-consumption-current": "50",
"co2-emissions-current": "123",
"mechanical-ventilation": "natural",
'photo-supply': 0,
"solar-water-heating-flag": "N",
"wind-turbine-count": 0,
"extension-count": 0,
"heat-loss-corridor": "no corridor",
"unheated-corridor-length": 0,
"mains-gas-flag": "Y",
"floor-height": 2.5,
"total-floor-area": 100,
"construction-age-band": "England and Wales: 1967-1975"
},
{
"lmk-key": 3,
"uprn": 3,
"number-habitable-rooms": 5,
"property-type": "House",
'inspection-date': '2023-06-01', 'some-other-key': 'duplicate-date',
'roof-description': 'Roof Description',
'walls-description': 'Walls Description', 'windows-description': 'Windows Description',
'mainheat-description': 'Main Heating Description', 'hotwater-description': 'Hot Water Description',
"transaction-type": "rental",
"lighting-description": "Good Lighting Efficiency",
"energy-consumption-current": "50",
"co2-emissions-current": "123",
"mechanical-ventilation": "natural",
'photo-supply': 0,
"solar-water-heating-flag": "N",
"wind-turbine-count": 0,
"extension-count": 0,
"heat-loss-corridor": "no corridor",
"unheated-corridor-length": 0,
"mains-gas-flag": "Y",
"floor-height": 2.5,
"total-floor-area": 100,
"construction-age-band": "England and Wales: 1967-1975"
}
]
}
class TestProperty:
@pytest.fixture(autouse=True)
def property_instance(self, mock_epc_client, mock_cleaner):
property_instance = Property(1, "AB12CD", "Test Address", epc_client=mock_epc_client)
return property_instance
@pytest.fixture(autouse=True)
def property_instance_dupe_data(self, mock_epc_client_dupe_data):
property_instance_dupe_data = Property(2, "AB12CD", "Test Address", epc_client=mock_epc_client_dupe_data)
return property_instance_dupe_data
@pytest.fixture
def mock_epc_client(self):
mock_epc_client = Mock(spec=EpcClient(auth_token="mocked_auth_token"))
mock_epc_client.domestic.search.return_value = mock_epc_response.copy()
mock_epc_client.auth_token = "mocked_auth_token"
return mock_epc_client
@pytest.fixture
def mock_epc_client_dupe_data(self):
mock_epc_client_dupe_data = Mock(spec=EpcClient(auth_token="mocked_auth_token"))
mock_epc_client_dupe_data.domestic.search.return_value = mock_epc_response_dupe.copy()
mock_epc_client_dupe_data.auth_token = "mocked_auth_token"
return mock_epc_client_dupe_data
@pytest.fixture
def mock_cleaner(self):
lighting_averages = [
{'lighting-description': 'good lighting efficiency', 'low-energy-lighting': 99.26666666666667},
{'lighting-description': 'excellent lighting efficiency', 'low-energy-lighting': 100.0},
{'lighting-description': 'below average lighting efficiency', 'low-energy-lighting': 0.0}
]
cleaner_spec = EpcClean(
data=[
{"roof-description": "Roof Description"},
{"walls-description": "Walls Description"},
{"windows-description": "Windows Description"},
{"mainheat-description": "Main Heating Description"},
{"hotwater-description": "Hot Water Description"},
{"lighting-description": "Good Lighting Efficiency"},
{"low-energy-lighting": 0}
],
lighting_averages=lighting_averages
)
mock_cleaner = Mock(spec=cleaner_spec)
walls_data = {
"original_description": "Walls Description",
"is_cavity_wall": True,
"is_solid_brick": False,
"is_timber_frame": False,
"is_system_built": False,
"is_park_home": False,
"is_cob": False,
"is_sandstone_or_limestone": False,
"is_granite_or_whinstone": False,
}
mock_cleaner.cleaned = {
"roof-description": [{"original_description": "Roof Description"}],
"walls-description": [walls_data],
"windows-description": [{"original_description": "Windows Description"}],
"mainheat-description": [{"original_description": "Main Heating Description"}],
"hotwater-description": [{"original_description": "Hot Water Description"}],
"lighting-description": [{"original_description": "Good Lighting Efficiency"}]
}
return mock_cleaner
def test_init(self, mock_epc_client):
inst1 = Property(0, "AB12CD", "Test Address", epc_client=mock_epc_client)
# Should be mocked auth token
assert inst1.epc_client.auth_token == "mocked_auth_token"
inst2 = Property(3, "AB12CD", "Test Address", epc_client=mock_epc_client)
assert inst2.epc_client.auth_token
inst3 = Property(4, "AB12CD", "Test Address", data={"some": "data"}, epc_client=mock_epc_client)
assert inst3.data == {"some": "data"}
data = inst3.search_address_epc()
assert data is None
def test_search_address_epc(self, property_instance):
# Call the method to test
property_instance.search_address_epc()
# Verify that the correct data is being returned
assert property_instance.data == mock_epc_response["rows"][0]
def test_search_address_epc_multiple_results(self, property_instance_dupe_data, mock_epc_client_dupe_data):
with pytest.raises(Exception, match="More than one result found for this address - investigate me"):
property_instance_dupe_data.search_address_epc()
def test_get_components(self, property_instance, mock_cleaner, mock_epc_client):
property_instance.search_address_epc()
property_instance.get_components(mock_cleaner.cleaned)
# Verify that the components are set correctly
assert property_instance.roof == {"original_description": "Roof Description"}
assert property_instance.walls == {
"original_description": "Walls Description",
"is_cavity_wall": True,
"is_solid_brick": False,
"is_timber_frame": False,
"is_system_built": False,
"is_park_home": False,
"is_cob": False,
"is_sandstone_or_limestone": False,
"is_granite_or_whinstone": False,
}
assert property_instance.windows == {"original_description": "Windows Description"}
assert property_instance.main_heating == {"original_description": "Main Heating Description"}
assert property_instance.hotwater == {"original_description": "Hot Water Description"}
assert property_instance.wall_type == "cavity"
def test_get_components_without_cleaned_data(self, property_instance, mock_cleaner):
# Modify the mock EpcClean to not have cleaned data
mock_cleaner.cleaned = {}
# Verify that ValueError is raised when EpcClean doesn't contain cleaned data
with pytest.raises(ValueError, match="Cleaner does not contain cleaned data"):
property_instance.get_components(mock_cleaner.cleaned)
def test_get_components_no_data(self, property_instance, mock_cleaner):
# Modify the mock cleaner to have no attributes for a specific description
mock_cleaner.cleaned = {
"roof-description": []
}
# Verify that ValueError is raised when no attributes are found
with pytest.raises(ValueError, match="Property does not contain data"):
property_instance.get_components(mock_cleaner.cleaned)
def test_get_components_no_attributes(self, property_instance, mock_cleaner):
# Modify the mock cleaner to have no attributes for a specific description
mock_cleaner.cleaned = {
"roof-description": []
}
property_instance.search_address_epc()
# Verify that ValueError is raised when no attributes are found
with pytest.raises(ValueError, match="Either No attributes or multiple found for roof-description"):
property_instance.get_components(mock_cleaner.cleaned)
def test_get_components_multiple_attributes(self, property_instance, mock_cleaner):
# This shouldn't happen - it would mean a cleaning error
property_instance.search_address_epc()
cleaned = {
"roof-description": [
{"original_description": "Roof Description"},
{"original_description": "Roof Description"}
]
}
# Verify that ValueError is raised when multiple attributes are found
with pytest.raises(ValueError, match="Either No attributes or multiple found for roof-description"):
property_instance.get_components(cleaned)