mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-07-19 17:03:02 +00:00
106 lines
3.9 KiB
Python
106 lines
3.9 KiB
Python
from __future__ import annotations
|
|
|
|
import pytest
|
|
|
|
from domain.epc.property_overrides.glazing_type import GlazingType
|
|
from domain.epc.property_overrides.glazing_mix_guard import glazing_mix_guard
|
|
|
|
|
|
def test_a_genuine_percentage_mix_classifies_as_mixed() -> None:
|
|
# Arrange — the bug: an aggregate mix the LLM would flatten to "Double".
|
|
description = "40% double glazing 2002 or later, 60% single glazing"
|
|
|
|
# Act
|
|
result = glazing_mix_guard(description)
|
|
|
|
# Assert — a mix defers to the cert's per-window glazing, not a whole-dwelling
|
|
# type.
|
|
assert result is GlazingType.MIXED
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"description",
|
|
[
|
|
"4% double glazing 2002 or later, 96% single glazing",
|
|
"10% double glazing 2002 or later, 90% single glazing", # exactly at threshold
|
|
"5% double glazing pre-2002, 95% single glazing",
|
|
],
|
|
)
|
|
def test_dominant_single_glazing_resolves_to_single(description: str) -> None:
|
|
# The bug: the LLM flattened a >= 90%-single dwelling onto its *minority* double
|
|
# type. Single glazing is era-free, so a dominant-single split is fully
|
|
# determined — the guard must claim it (SINGLE) rather than defer to the LLM.
|
|
|
|
# Act
|
|
result = glazing_mix_guard(description)
|
|
|
|
# Assert
|
|
assert result is GlazingType.SINGLE
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("description", "expected"),
|
|
[
|
|
# >= 90% double with a *stated* era is era-pinned — the LLM otherwise
|
|
# flattens it onto the 4% minority single (the symmetric bug to the
|
|
# dominant-single case above).
|
|
("96% double glazing 2002 or later, 4% single glazing", GlazingType.DOUBLE_POST_2002),
|
|
("95% double glazing pre-2002, 5% single glazing", GlazingType.DOUBLE_PRE_2002),
|
|
("90% double glazing 2002 or later, 10% single glazing", GlazingType.DOUBLE_POST_2002),
|
|
# Triple is era-bearing too — resolve when the era is stated.
|
|
("92% triple glazing pre-2002, 8% single glazing", GlazingType.TRIPLE_PRE_2002),
|
|
("91% triple glazing 2002 or later, 9% single glazing", GlazingType.TRIPLE_POST_2002),
|
|
],
|
|
)
|
|
def test_dominant_era_stated_double_or_triple_resolves_deterministically(
|
|
description: str, expected: GlazingType
|
|
) -> None:
|
|
# Act
|
|
result = glazing_mix_guard(description)
|
|
|
|
# Assert — a dominant double/triple whose era is stated is fully determined, so
|
|
# the guard claims it rather than trusting the LLM.
|
|
assert result is expected
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"description",
|
|
[
|
|
"95% secondary glazing (sap 9.94), 5% single glazing",
|
|
"90% secondary glazing, 10% double glazing 2002 or later",
|
|
],
|
|
)
|
|
def test_dominant_secondary_glazing_resolves_to_secondary(description: str) -> None:
|
|
# Secondary glazing is era-free like single (SAP10 code 5, U = 2.9 regardless
|
|
# of install year), so a dominant-secondary split is fully determined — the
|
|
# guard must claim it rather than let the LLM flatten it onto the minority
|
|
# type (Model#1416).
|
|
|
|
# Act
|
|
result = glazing_mix_guard(description)
|
|
|
|
# Assert
|
|
assert result is GlazingType.SECONDARY
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"description",
|
|
[
|
|
"100% double glazing 2002 or later", # uniform — one type
|
|
"100% secondary glazing (sap 9.94)", # uniform — one type
|
|
"90% double glazing unknown age, 10% single glazing", # dominant but era unstated
|
|
"80% double glazing 2002 or later, 20% double glazing pre-2002", # same base type
|
|
"some double glazing and a bit of single", # unparseable — no percentages
|
|
"",
|
|
],
|
|
)
|
|
def test_uniform_or_ambiguous_glazing_defers_to_the_llm(description: str) -> None:
|
|
# The guard only claims a genuine mix or a fully-determined dominant split. A
|
|
# uniform assertion, a dominant split whose era is unstated ("unknown age" — the
|
|
# era is genuinely ambiguous), or a varied phrasing is left for the LLM.
|
|
|
|
# Act
|
|
result = glazing_mix_guard(description)
|
|
|
|
# Assert
|
|
assert result is None
|