mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +00:00
test(fixtures): build_epc() deep-copies its windows so callers can't leak state
The worksheet build_epc() fixtures wrapped a module-level SECTION_6_VERTICAL_ WINDOWS tuple in list(), so every call returned the SAME SapWindow objects. A test that mutated a returned window (the glazing slices flip glazing_type to single) leaked that change into every later build_epc() -- which surfaced as double_glazing-product failures in the first-run integration tests only when test_console ran first in the same process. Deep-copy the windows per call in all six fixtures (000474/477/480/487/490/516) so each EpcPropertyData owns an independent window graph, and drop the now-redundant defensive copy at the glazing test's call site. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
456a81df0a
commit
4783ff9dfd
7 changed files with 33 additions and 12 deletions
|
|
@ -19,6 +19,7 @@ Distinct features vs prior fixtures:
|
|||
first 5.27) — the upper storey is smaller than the ground
|
||||
"""
|
||||
|
||||
import copy
|
||||
from typing import Optional
|
||||
|
||||
from datatypes.epc.domain.epc_property_data import (
|
||||
|
|
@ -164,7 +165,10 @@ def build_epc() -> EpcPropertyData:
|
|||
heated_rooms_count=3,
|
||||
door_count=2,
|
||||
low_energy_fixed_lighting_bulbs_count=8,
|
||||
sap_windows=list(SECTION_6_VERTICAL_WINDOWS),
|
||||
# Deep-copy so each build_epc() owns its windows (the module-level
|
||||
# SECTION_6_VERTICAL_WINDOWS tuple holds shared SapWindow objects; a
|
||||
# caller mutating a returned window would otherwise leak across calls).
|
||||
sap_windows=[copy.deepcopy(window) for window in SECTION_6_VERTICAL_WINDOWS],
|
||||
percent_draughtproofed=78,
|
||||
extensions_count=2,
|
||||
blocked_chimneys_count=0,
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ Distinct features vs prior fixtures:
|
|||
flat ceiling — just stud walls (1.5/1.3 height) + slopes
|
||||
"""
|
||||
|
||||
import copy
|
||||
from typing import Optional
|
||||
|
||||
from datatypes.epc.domain.epc_property_data import (
|
||||
|
|
@ -137,7 +138,10 @@ def build_epc() -> EpcPropertyData:
|
|||
door_count=2,
|
||||
percent_draughtproofed=100,
|
||||
low_energy_fixed_lighting_bulbs_count=SECTION_5_BULB_COUNT_LEL,
|
||||
sap_windows=list(SECTION_6_VERTICAL_WINDOWS),
|
||||
# Deep-copy so each build_epc() owns its windows (the module-level
|
||||
# SECTION_6_VERTICAL_WINDOWS tuple holds shared SapWindow objects; a
|
||||
# caller mutating a returned window would otherwise leak across calls).
|
||||
sap_windows=[copy.deepcopy(window) for window in SECTION_6_VERTICAL_WINDOWS],
|
||||
blocked_chimneys_count=0,
|
||||
dwelling_type="Mid-Terrace house",
|
||||
built_form="Mid-Terrace",
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ Differs from 000487 along several useful axes:
|
|||
- No alternative wall (vs 1 timber-frame alt wall on the extension)
|
||||
"""
|
||||
|
||||
import copy
|
||||
from typing import Optional
|
||||
|
||||
from datatypes.epc.domain.epc_property_data import (
|
||||
|
|
@ -180,7 +181,10 @@ def build_epc() -> EpcPropertyData:
|
|||
door_count=2, # cert lodges 2 doors total
|
||||
percent_draughtproofed=100,
|
||||
low_energy_fixed_lighting_bulbs_count=SECTION_5_BULB_COUNT_LEL,
|
||||
sap_windows=list(SECTION_6_VERTICAL_WINDOWS),
|
||||
# Deep-copy so each build_epc() owns its windows (the module-level
|
||||
# SECTION_6_VERTICAL_WINDOWS tuple holds shared SapWindow objects; a
|
||||
# caller mutating a returned window would otherwise leak across calls).
|
||||
sap_windows=[copy.deepcopy(window) for window in SECTION_6_VERTICAL_WINDOWS],
|
||||
extensions_count=1,
|
||||
blocked_chimneys_count=0,
|
||||
dwelling_type="Mid-Terrace house",
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ values captured below. Treat the LINE_X constants as authoritative; if
|
|||
they diverge from our code, the bug is on our side.
|
||||
"""
|
||||
|
||||
import copy
|
||||
from typing import Optional
|
||||
|
||||
from datatypes.epc.domain.epc_property_data import (
|
||||
|
|
@ -190,7 +191,10 @@ def build_epc() -> EpcPropertyData:
|
|||
door_count=1,
|
||||
percent_draughtproofed=100,
|
||||
low_energy_fixed_lighting_bulbs_count=SECTION_5_BULB_COUNT_LEL,
|
||||
sap_windows=list(SECTION_6_VERTICAL_WINDOWS),
|
||||
# Deep-copy so each build_epc() owns its windows (the module-level
|
||||
# SECTION_6_VERTICAL_WINDOWS tuple holds shared SapWindow objects; a
|
||||
# caller mutating a returned window would otherwise leak across calls).
|
||||
sap_windows=[copy.deepcopy(window) for window in SECTION_6_VERTICAL_WINDOWS],
|
||||
extensions_count=1,
|
||||
blocked_chimneys_count=0,
|
||||
dwelling_type="Enclosed Mid-Terrace house",
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ Distinct features vs prior fixtures:
|
|||
- DP = 100%, so (15) = 0.05 (lowest window-infiltration component)
|
||||
"""
|
||||
|
||||
import copy
|
||||
from typing import Optional
|
||||
|
||||
from datatypes.epc.domain.epc_property_data import (
|
||||
|
|
@ -146,7 +147,11 @@ def build_epc() -> EpcPropertyData:
|
|||
heated_rooms_count=4,
|
||||
door_count=2,
|
||||
low_energy_fixed_lighting_bulbs_count=8,
|
||||
sap_windows=list(SECTION_6_VERTICAL_WINDOWS),
|
||||
# Deep-copy so each build_epc() owns its windows: SECTION_6_VERTICAL_
|
||||
# WINDOWS is a module-level tuple of shared SapWindow objects, and a
|
||||
# caller that mutates a returned window (e.g. flipping glazing_type to
|
||||
# test a glazing measure) would otherwise leak into every later call.
|
||||
sap_windows=[copy.deepcopy(window) for window in SECTION_6_VERTICAL_WINDOWS],
|
||||
percent_draughtproofed=100,
|
||||
extensions_count=1,
|
||||
blocked_chimneys_count=0,
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ Distinct features vs prior fixtures:
|
|||
as 000480 but on a single-part dwelling
|
||||
"""
|
||||
|
||||
import copy
|
||||
from typing import Optional
|
||||
|
||||
from datatypes.epc.domain.epc_property_data import (
|
||||
|
|
@ -175,7 +176,10 @@ def build_epc() -> EpcPropertyData:
|
|||
],
|
||||
percent_draughtproofed=75,
|
||||
low_energy_fixed_lighting_bulbs_count=SECTION_5_BULB_COUNT_LEL,
|
||||
sap_windows=list(SECTION_6_VERTICAL_WINDOWS),
|
||||
# Deep-copy so each build_epc() owns its windows (the module-level
|
||||
# SECTION_6_VERTICAL_WINDOWS tuple holds shared SapWindow objects; a
|
||||
# caller mutating a returned window would otherwise leak across calls).
|
||||
sap_windows=[copy.deepcopy(window) for window in SECTION_6_VERTICAL_WINDOWS],
|
||||
blocked_chimneys_count=0,
|
||||
dwelling_type="Mid-Terrace house",
|
||||
built_form="Mid-Terrace",
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
import copy
|
||||
import dataclasses
|
||||
|
||||
import pytest
|
||||
|
|
@ -117,11 +116,8 @@ def test_run_modelling_listed_building_yields_no_wall_insulation() -> None:
|
|||
|
||||
def _single_glazed_epc() -> EpcPropertyData:
|
||||
"""The cavity/floor dwelling with all windows single-glazed — the glazing
|
||||
generator's trigger, sized so the upgrade reaches the optimised package.
|
||||
|
||||
`build_epc()` shares its window objects across calls, so deep-copy before
|
||||
mutating to avoid leaking single-glazing into other tests' baselines."""
|
||||
epc: EpcPropertyData = copy.deepcopy(_build_uninsulated_cavity_and_floor_epc())
|
||||
generator's trigger, sized so the upgrade reaches the optimised package."""
|
||||
epc: EpcPropertyData = _build_uninsulated_cavity_and_floor_epc()
|
||||
for window in epc.sap_windows:
|
||||
window.glazing_type = 1 # SAP10.2 Table U2 code 1 = single.
|
||||
return epc
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue