test(lookup): restore sys.modules after loading the sso plugins fresh

test_sso.py, test_sso_oidc_plugin.py and test_sso_proxy_consumers.py evict utils.cache.applications, utils.cache and the roles packages from sys.modules to import their plugin against fresh modules, and never put the originals back. A later test module in the same worker then held two copies of utils.cache.applications: plugins.lookup.applications, imported earlier, kept calling the old one, while test_email patched and reset the new one. Its carrier tests counted 0 renders and failed (CI run 40869769501, test_email.py:556 and :570, and the IAM merge gate), depending only on which modules xdist placed in one worker.

_load_module now runs inside mock.patch.dict(sys.modules): the plugin keeps the fresh modules it was built against, and sys.modules returns to its prior state, so the next module sees exactly what it would have without these tests. `pytest test_sso.py test_email.py` failed the two carrier tests before and passes 67/67 with the three SSO modules first.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
kevinveenbirkenbachandClaude Opus 5.5 committed 2026-10-29 13:52:02 +01:00
1 parent ff288a3dd4
commit ec0fde6561
3 files changed
+54 -51

No files matched your search

+19 -18
View File
@@ -19,25 +19,26 @@ from . import PROJECT_ROOT
def _load_module(rel_path: str, name: str):
for key in (
"utils.roles.applications.config",
"utils.roles.applications",
"utils",
"utils.cache.applications",
"utils.cache",
"utils.roles.applications.services.sso",
"utils.roles.applications.services",
):
sys.modules.pop(key, None)
importlib.import_module("utils.roles.applications.config")
importlib.import_module("utils.cache.applications")
importlib.import_module("utils.roles.applications.services.sso")
with mock.patch.dict(sys.modules):
for key in (
"utils.roles.applications.config",
"utils.roles.applications",
"utils",
"utils.cache.applications",
"utils.cache",
"utils.roles.applications.services.sso",
"utils.roles.applications.services",
):
sys.modules.pop(key, None)
importlib.import_module("utils.roles.applications.config")
importlib.import_module("utils.cache.applications")
importlib.import_module("utils.roles.applications.services.sso")
path = PROJECT_ROOT / rel_path
spec = importlib.util.spec_from_file_location(name, str(path))
mod = importlib.util.module_from_spec(spec)
assert spec and spec.loader
spec.loader.exec_module(mod)
path = PROJECT_ROOT / rel_path
spec = importlib.util.spec_from_file_location(name, str(path))
mod = importlib.util.module_from_spec(spec)
assert spec and spec.loader
spec.loader.exec_module(mod)
return mod
@@ -13,22 +13,23 @@ def _load_module(rel_path: str, name: str):
"""Import ``rel_path`` fresh, evicting sibling-test stubs of
``utils.roles.applications.config`` from ``sys.modules`` first.
"""
for key in (
"utils.roles.applications.config",
"utils.roles.applications",
"utils",
"utils.cache.applications",
"utils.cache",
):
sys.modules.pop(key, None)
importlib.import_module("utils.roles.applications.config")
importlib.import_module("utils.cache.applications")
with mock.patch.dict(sys.modules):
for key in (
"utils.roles.applications.config",
"utils.roles.applications",
"utils",
"utils.cache.applications",
"utils.cache",
):
sys.modules.pop(key, None)
importlib.import_module("utils.roles.applications.config")
importlib.import_module("utils.cache.applications")
path = PROJECT_ROOT / rel_path
spec = importlib.util.spec_from_file_location(name, str(path))
mod = importlib.util.module_from_spec(spec)
assert spec and spec.loader
spec.loader.exec_module(mod)
path = PROJECT_ROOT / rel_path
spec = importlib.util.spec_from_file_location(name, str(path))
mod = importlib.util.module_from_spec(spec)
assert spec and spec.loader
spec.loader.exec_module(mod)
return mod
@@ -19,25 +19,26 @@ from . import PROJECT_ROOT
def _load_module(rel_path: str, name: str):
for key in (
"utils.roles.applications.config",
"utils.roles.applications",
"utils",
"utils.cache.applications",
"utils.cache",
"utils.roles.applications.services.sso",
"utils.roles.applications.services",
):
sys.modules.pop(key, None)
importlib.import_module("utils.roles.applications.config")
importlib.import_module("utils.cache.applications")
importlib.import_module("utils.roles.applications.services.sso")
with mock.patch.dict(sys.modules):
for key in (
"utils.roles.applications.config",
"utils.roles.applications",
"utils",
"utils.cache.applications",
"utils.cache",
"utils.roles.applications.services.sso",
"utils.roles.applications.services",
):
sys.modules.pop(key, None)
importlib.import_module("utils.roles.applications.config")
importlib.import_module("utils.cache.applications")
importlib.import_module("utils.roles.applications.services.sso")
path = PROJECT_ROOT / rel_path
spec = importlib.util.spec_from_file_location(name, str(path))
mod = importlib.util.module_from_spec(spec)
assert spec and spec.loader
spec.loader.exec_module(mod)
path = PROJECT_ROOT / rel_path
spec = importlib.util.spec_from_file_location(name, str(path))
mod = importlib.util.module_from_spec(spec)
assert spec and spec.loader
spec.loader.exec_module(mod)
return mod