diff --git a/policyengine_uk/tests/conftest.py b/policyengine_uk/tests/conftest.py index deee0cc756..56e18f3671 100644 --- a/policyengine_uk/tests/conftest.py +++ b/policyengine_uk/tests/conftest.py @@ -36,10 +36,10 @@ def pytest_collection_modifyitems(config, items): # a module named "__" and registers it in # sys.modules, where it stays after the system is garbage collected. Every # Simulation builds its own system, so each one leaves about 1,000 modules -# (roughly 10 MB) behind, and the property tests build hundreds: one test -# process grew to 15.7 GB on a 16 GB CI runner. After each test, drop the -# modules of systems that no longer exist; live systems keep theirs. Remove -# this once policyengine-core stops leaking them +# (roughly 10 MB) behind, and the property tests build hundreds: running the +# suite serially used 99% of a 16 GB CI runner's memory. After each test, drop +# the modules of systems that no longer exist; live systems keep theirs. +# Remove this once policyengine-core stops leaking them # (PolicyEngine/policyengine-core#520). _VARIABLE_MODULE_NAME = re.compile(r"(\d+)_-?\d+_") @@ -66,8 +66,8 @@ def release_dead_variable_modules(max_owners: int = 8) -> int: for owner, names in owners.items(): if owner not in live: for name in names: - sys.modules.pop(name, None) - released += len(names) + if sys.modules.pop(name, None) is not None: + released += 1 return released diff --git a/policyengine_uk/tests/test_variable_module_release.py b/policyengine_uk/tests/test_variable_module_release.py index 61d2047ccd..3d52036c73 100644 --- a/policyengine_uk/tests/test_variable_module_release.py +++ b/policyengine_uk/tests/test_variable_module_release.py @@ -4,14 +4,18 @@ under the system's id and never removes them. The conftest's ``release_dead_variable_modules`` drops those of systems that no longer exist, which keeps a long test process's memory flat. If core stops leaking the -modules (PolicyEngine/policyengine-core#520), the precondition below fails -and the workaround can go. +modules (PolicyEngine/policyengine-core#520), the first test skips with a +note to remove the workaround, rather than failing every PR after a core +upgrade. If core keeps leaking but names the modules differently, it fails, +because the release would then silently do nothing. """ import gc import sys from pathlib import Path +import pytest + from policyengine_uk import Simulation SITUATION = { @@ -41,10 +45,18 @@ def test_dead_systems_modules_are_released_and_live_ones_kept(request): dropped_owner = str(id(dropped.tax_benefit_system)) expected = dropped.calculate("income_tax", 2026) - assert _modules_of(dropped_owner), ( - "policyengine-core no longer registers variable modules under the " - "system's id; the conftest workaround may no longer be needed" - ) + # The module core loaded the income_tax variable from, for this system. + module = type(dropped.tax_benefit_system.variables["income_tax"]).__module__ + if module not in sys.modules: + pytest.skip( + "policyengine-core no longer keeps variable modules in sys.modules " + "(policyengine-core#520 fixed?); remove " + "release_dead_variable_modules from conftest.py and this test" + ) + # Core still keeps them, so the conftest pattern must still recognise them, + # or the release would silently do nothing. + assert module.startswith(dropped_owner + "_"), module + assert _conftest(request)._VARIABLE_MODULE_NAME.match(module), module del dropped gc.collect()