Skip to content

Commit 08e53b2

Browse files
jeremymanningclaude
andcommitted
Fix test isolation issues for GitHub Actions compatibility
Key fixes implemented: - Added preserve_modules pytest fixture to save/restore module state between tests - Fixed test_widget_without_ipython to properly clean up module cache - Resolved all test failures caused by module state corruption Technical solutions: 1. Module state preservation fixture prevents tests from corrupting each other 2. Proper cleanup in test_widget_without_ipython restores original module 3. All GitHub Actions compatibility tests now use preserve_modules fixture Results: - All 293 tests now pass consistently (was failing 7-17 tests) - Tests pass both individually and when run in full suite - GitHub Actions simulation works correctly without errors 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 6f6aab2 commit 08e53b2

File tree

2 files changed

+49
-10
lines changed

2 files changed

+49
-10
lines changed

tests/test_github_actions_compat.py

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,35 @@
1111
import pytest
1212

1313

14+
@pytest.fixture
15+
def preserve_modules():
16+
"""Preserve module state before and after test."""
17+
# Save original modules
18+
original_modules = {}
19+
modules_to_preserve = [
20+
mod for mod in sys.modules.keys() if mod.startswith("clustrix")
21+
]
22+
for mod in modules_to_preserve:
23+
original_modules[mod] = sys.modules.get(mod)
24+
25+
yield
26+
27+
# Clear any test modules
28+
modules_to_clear = [mod for mod in sys.modules.keys() if mod.startswith("clustrix")]
29+
for mod in modules_to_clear:
30+
if mod in sys.modules:
31+
del sys.modules[mod]
32+
33+
# Restore original modules
34+
for mod, value in original_modules.items():
35+
if value is not None:
36+
sys.modules[mod] = value
37+
38+
1439
class TestGitHubActionsCompatibility:
1540
"""Test compatibility with GitHub Actions CI/CD environment."""
1641

17-
def test_notebook_magic_without_dependencies(self):
42+
def test_notebook_magic_without_dependencies(self, preserve_modules):
1843
"""Test notebook magic works when IPython/ipywidgets are completely unavailable."""
1944
# Clear any existing clustrix modules
2045
modules_to_clear = [
@@ -56,7 +81,7 @@ def test_notebook_magic_without_dependencies(self):
5681
# Should return None (graceful failure)
5782
assert result is None
5883

59-
def test_widget_creation_without_dependencies(self):
84+
def test_widget_creation_without_dependencies(self, preserve_modules):
6085
"""Test widget creation fails gracefully when dependencies missing."""
6186
# Clear any existing clustrix modules
6287
modules_to_clear = [
@@ -80,7 +105,7 @@ def test_widget_creation_without_dependencies(self):
80105
):
81106
EnhancedClusterConfigWidget()
82107

83-
def test_auto_display_without_dependencies(self):
108+
def test_auto_display_without_dependencies(self, preserve_modules):
84109
"""Test auto display function handles missing dependencies gracefully."""
85110
# Clear any existing clustrix modules
86111
modules_to_clear = [
@@ -101,7 +126,7 @@ def test_auto_display_without_dependencies(self):
101126
# Should not raise any exceptions
102127
auto_display_on_import()
103128

104-
def test_load_ipython_extension_without_dependencies(self):
129+
def test_load_ipython_extension_without_dependencies(self, preserve_modules):
105130
"""Test IPython extension loading handles missing dependencies."""
106131
# Clear any existing clustrix modules
107132
modules_to_clear = [
@@ -132,7 +157,7 @@ def test_load_ipython_extension_without_dependencies(self):
132157
# Should not try to register magic function
133158
assert not mock_ipython.register_magic_function.called
134159

135-
def test_module_import_chain_without_dependencies(self):
160+
def test_module_import_chain_without_dependencies(self, preserve_modules):
136161
"""Test the full module import chain works without dependencies."""
137162
# Clear any existing clustrix modules
138163
modules_to_clear = [

tests/test_notebook_magic.py

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -186,11 +186,25 @@ def test_widget_auto_display_flag(self, mock_ipython_environment):
186186

187187
def test_widget_without_ipython(self):
188188
"""Test widget creation fails without IPython."""
189-
with patch("clustrix.notebook_magic.IPYTHON_AVAILABLE", False):
190-
with pytest.raises(
191-
ImportError, match="IPython and ipywidgets are required"
192-
):
193-
EnhancedClusterConfigWidget()
189+
# Clear the module cache to ensure clean import
190+
import sys
191+
192+
original_module = sys.modules.get("clustrix.notebook_magic")
193+
try:
194+
if "clustrix.notebook_magic" in sys.modules:
195+
del sys.modules["clustrix.notebook_magic"]
196+
197+
with patch.dict("sys.modules", {"IPython": None, "ipywidgets": None}):
198+
from clustrix.notebook_magic import EnhancedClusterConfigWidget
199+
200+
with pytest.raises(
201+
ImportError, match="IPython and ipywidgets are required"
202+
):
203+
EnhancedClusterConfigWidget()
204+
finally:
205+
# Restore the original module
206+
if original_module:
207+
sys.modules["clustrix.notebook_magic"] = original_module
194208

195209
def test_config_file_loading(self, mock_ipython_environment):
196210
"""Test configuration loading from files."""

0 commit comments

Comments
 (0)