mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +00:00
fixing unit tests for Property class
This commit is contained in:
parent
dd90065874
commit
f8a4884deb
7 changed files with 115 additions and 55 deletions
|
|
@ -9,4 +9,5 @@ omit =
|
|||
model_data/plotting/*
|
||||
recommendations/rdsap_tables.py
|
||||
model_data/simulation_system/*
|
||||
model_data/cleaner_app.py
|
||||
model_data/cleaner_app.py
|
||||
backend/app/*
|
||||
2
.idea/Model.iml
generated
2
.idea/Model.iml
generated
|
|
@ -7,7 +7,7 @@
|
|||
<sourceFolder url="file://$MODULE_DIR$/open_uprn" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/recommendations" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="jdk" jdkName="Python 3.10 (backend)" jdkType="Python SDK" />
|
||||
<orderEntry type="jdk" jdkName="Python 3.10 (model_data)" jdkType="Python SDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
2
.idea/misc.xml
generated
2
.idea/misc.xml
generated
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.10 (backend)" project-jdk-type="Python SDK" />
|
||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.10 (model_data)" project-jdk-type="Python SDK" />
|
||||
<component name="PythonCompatibilityInspectionAdvertiser">
|
||||
<option name="version" value="3" />
|
||||
</component>
|
||||
|
|
|
|||
|
|
@ -99,12 +99,6 @@ walls_decile_data = {
|
|||
'Decile 9', 'Decile 10'], 'decile_boundaries': [6., 49., 51., 55., 64., 71., 76., 83., 96.,
|
||||
120., 2279.]}
|
||||
|
||||
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}
|
||||
]
|
||||
|
||||
|
||||
def filter_materials(materials):
|
||||
materials_by_type = defaultdict(list)
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import pytest
|
|||
import pandas as pd
|
||||
from unittest.mock import Mock
|
||||
from epc_api.client import EpcClient
|
||||
from model_data.Property import Property
|
||||
from backend.Property import Property
|
||||
from open_uprn.OpenUprnClient import OpenUprnClient
|
||||
from model_data.EpcClean import EpcClean
|
||||
|
||||
|
|
@ -19,6 +19,18 @@ mock_epc_response = {
|
|||
"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
|
||||
},
|
||||
{
|
||||
"inspection-date": "2023-05-01",
|
||||
|
|
@ -30,6 +42,18 @@ mock_epc_response = {
|
|||
"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
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -42,6 +66,18 @@ mock_epc_response_dupe = {
|
|||
'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
|
||||
},
|
||||
{
|
||||
'inspection-date': '2023-05-01', 'some-other-key': 'some-other-value',
|
||||
|
|
@ -50,6 +86,18 @@ mock_epc_response_dupe = {
|
|||
'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
|
||||
},
|
||||
{
|
||||
'inspection-date': '2023-06-01', 'some-other-key': 'duplicate-date',
|
||||
|
|
@ -58,6 +106,18 @@ mock_epc_response_dupe = {
|
|||
'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
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -66,11 +126,11 @@ mock_epc_response_dupe = {
|
|||
class TestProperty:
|
||||
@pytest.fixture(autouse=True)
|
||||
def property_instance(self, mock_epc_client, mock_open_uprn_client, mock_cleaner):
|
||||
return Property("AB12CD", "Test Address", epc_client=mock_epc_client)
|
||||
return Property(1, "AB12CD", "Test Address", epc_client=mock_epc_client)
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def property_instance_dupe_data(self, mock_epc_client_dupe_data):
|
||||
return Property("AB12CD", "Test Address", epc_client=mock_epc_client_dupe_data)
|
||||
return Property(2, "AB12CD", "Test Address", epc_client=mock_epc_client_dupe_data)
|
||||
|
||||
@pytest.fixture
|
||||
def mock_epc_client(self):
|
||||
|
|
@ -99,15 +159,26 @@ class TestProperty:
|
|||
|
||||
@pytest.fixture
|
||||
def mock_cleaner(self):
|
||||
mock_cleaner = Mock(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-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)
|
||||
mock_cleaner.cleaned = {
|
||||
"roof-description": [{"original_description": "Roof Description"}],
|
||||
"walls-description": [{"original_description": "Walls Description"}],
|
||||
|
|
@ -119,14 +190,14 @@ class TestProperty:
|
|||
return mock_cleaner
|
||||
|
||||
def test_init(self, mock_epc_client):
|
||||
inst1 = Property("AB12CD", "Test Address", epc_client=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("AB12CD", "Test Address")
|
||||
inst2 = Property(3, "AB12CD", "Test Address")
|
||||
assert inst2.epc_client.auth_token
|
||||
|
||||
inst3 = Property("AB12CD", "Test Address", data={"some": "data"})
|
||||
inst3 = Property(4, "AB12CD", "Test Address", data={"some": "data"})
|
||||
assert inst3.data == {"some": "data"}
|
||||
|
||||
data = inst3.search_address_epc()
|
||||
|
|
@ -143,29 +214,9 @@ class TestProperty:
|
|||
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_coordinates(self, property_instance, mock_open_uprn_client):
|
||||
# Set up the mock OpenUprnClient
|
||||
property_instance.data = {"uprn": 12345}
|
||||
property_instance.get_coordinates(mock_open_uprn_client)
|
||||
|
||||
# Verify that the coordinates are set correctly
|
||||
assert property_instance.coordinates == {
|
||||
"uprn": 12345,
|
||||
"longitude": 1.2345,
|
||||
"latitude": 2.3456
|
||||
}
|
||||
|
||||
def test_get_coordinates_without_open_uprn_data(self, property_instance, mock_open_uprn_client):
|
||||
# Modify the mock OpenUprnClient to not have read any data
|
||||
mock_open_uprn_client.data = None
|
||||
|
||||
# Verify that ValueError is raised when OpenUprnClient data is None
|
||||
with pytest.raises(ValueError, match="OpenUprnClient has not read data"):
|
||||
property_instance.get_coordinates(mock_open_uprn_client)
|
||||
|
||||
def test_get_components(self, property_instance, mock_cleaner, mock_epc_client):
|
||||
property_instance.search_address_epc()
|
||||
property_instance.get_components(mock_cleaner)
|
||||
property_instance.get_components(mock_cleaner.cleaned)
|
||||
|
||||
# Verify that the components are set correctly
|
||||
assert property_instance.roof == {"original_description": "Roof Description"}
|
||||
|
|
@ -180,7 +231,7 @@ class TestProperty:
|
|||
|
||||
# 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)
|
||||
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
|
||||
|
|
@ -190,7 +241,7 @@ class TestProperty:
|
|||
|
||||
# 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)
|
||||
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
|
||||
|
|
@ -201,12 +252,12 @@ class TestProperty:
|
|||
|
||||
# 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)
|
||||
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()
|
||||
mock_cleaner.cleaned = {
|
||||
cleaned = {
|
||||
"roof-description": [
|
||||
{"original_description": "Roof Description"},
|
||||
{"original_description": "Roof Description"}
|
||||
|
|
@ -215,4 +266,4 @@ class TestProperty:
|
|||
|
||||
# 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(mock_cleaner)
|
||||
property_instance.get_components(cleaned)
|
||||
|
|
|
|||
|
|
@ -13,14 +13,28 @@ class LightingAttributes:
|
|||
def __init__(self, description, averages):
|
||||
self.description: str = clean_description(description.lower())
|
||||
|
||||
translation = self.WELSH_TEXT.get(self.description)
|
||||
if translation:
|
||||
self.nodata = False
|
||||
self.description = translation
|
||||
self.welsh_translation_search()
|
||||
|
||||
self.description = correct_spelling(self.description)
|
||||
self.averages = averages
|
||||
|
||||
def welsh_translation_search(self):
|
||||
"""
|
||||
For welsh text describing the percentage of low energy lighting, we match the regular
|
||||
expression and perform the translation
|
||||
"""
|
||||
lel_match = re.search(r"goleuadau ynni-isel mewn (\d+)%? ogçör mannau gosod", self.description)
|
||||
|
||||
if lel_match:
|
||||
# Perform the actual translation
|
||||
percentage = lel_match.group(1)
|
||||
self.description = f"low energy lighting in {percentage}% of fixed outlets"
|
||||
else:
|
||||
translation = self.WELSH_TEXT.get(self.description)
|
||||
if translation:
|
||||
self.nodata = False
|
||||
self.description = translation
|
||||
|
||||
def process(self):
|
||||
|
||||
description = self.description
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
[pytest]
|
||||
pythonpath = .
|
||||
addopts = --cov-report term-missing --cov=model_data --cov=recommendations
|
||||
testpaths = model_data/tests recommendations/tests
|
||||
testpaths = model_data/tests recommendations/tests backend/tests
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue