test(visualization): isolate optional dependency mocks (#897)

* test(visualization): isolate optional dependency mocks

* test(visualization): stop requiring Plotly in unit tests

Removing the global sys.modules stubs left the tests that patch
`...go.Bar`, or call a visualizer, with nothing standing in for the
module level `px` and `go` aliases. Those are None when Plotly is
missing, so patch resolution and _check_dependencies() both failed.

Add a helper that substitutes a double only for the aliases that are
None, leaving the real module in place when Plotly is installed.

---------
This commit is contained in:
Luan Taraschi
2026-08-20 17:58:20 +05:00
committed by GitHub
parent 54c274e02c
commit c5d382ee81
7 changed files with 187 additions and 245 deletions
View File
+29
View File
@@ -0,0 +1,29 @@
"""Shared helper for visualization tests.
The visualization modules treat Plotly as optional: they bind ``px``, ``go`` and
``make_subplots`` to ``None`` when the import fails, and raise ``ProcessingError``
from ``_check_dependencies()``. Tests that exercise a Plotly-backed path need
those names to be usable, otherwise ``patch("...go.Figure")`` fails on ``None``
and the visualizers refuse to run.
``plotly_doubles`` fills in a double for each alias that is ``None``, so the
tests describe their own requirements instead of depending on whether Plotly
happens to be installed. When Plotly is installed the aliases are left alone and
the patches keep asserting against the real attribute names.
"""
from contextlib import ExitStack, contextmanager
from unittest.mock import MagicMock, patch
PLOTLY_ALIASES = ("px", "go", "make_subplots")
@contextmanager
def plotly_doubles(*modules):
"""Stand in for the module-level Plotly aliases that are unavailable."""
with ExitStack() as stack:
for module in modules:
for alias in PLOTLY_ALIASES:
if getattr(module, alias, "unused") is None:
stack.enter_context(patch.object(module, alias, MagicMock()))
yield
@@ -9,27 +9,16 @@ and must raise a clear ProcessingError for anything else.
"""
import contextlib
import sys
import unittest
from dataclasses import dataclass, field
from typing import List
from unittest.mock import MagicMock, patch
# ---------------------------------------------------------------------------
# Stub out heavy optional deps before importing the module under test
# ---------------------------------------------------------------------------
sys.modules.setdefault("matplotlib", MagicMock())
sys.modules.setdefault("matplotlib.pyplot", MagicMock())
sys.modules.setdefault("matplotlib.patches", MagicMock())
sys.modules.setdefault("plotly", MagicMock())
sys.modules.setdefault("plotly.express", MagicMock())
sys.modules.setdefault("plotly.graph_objects", MagicMock())
sys.modules.setdefault("plotly.subplots", MagicMock())
sys.modules.setdefault("graphviz", MagicMock())
sys.modules.setdefault("seaborn", MagicMock())
from semantica.utils.exceptions import ProcessingError # noqa: E402
from semantica.visualization import kg_visualizer # noqa: E402
from semantica.visualization.kg_visualizer import KGVisualizer # noqa: E402
from tests.visualization._plotly_doubles import plotly_doubles # noqa: E402
# ---------------------------------------------------------------------------
# Minimal fixtures
@@ -191,10 +180,6 @@ class TestVisualizeNetworkAcceptsKGObject(unittest.TestCase):
def _run_visualize_network(self, graph_arg):
"""Run visualize_network with all Plotly internals mocked."""
mock_fig = MagicMock()
mock_go = sys.modules["plotly.graph_objects"]
mock_go.Figure.return_value = mock_fig
mock_go.Scatter.return_value = MagicMock()
mock_go.Layout.return_value = MagicMock()
viz = _make_viz()
@@ -207,6 +192,10 @@ class TestVisualizeNetworkAcceptsKGObject(unittest.TestCase):
# ColorPalette helpers
with (
plotly_doubles(kg_visualizer),
patch("semantica.visualization.kg_visualizer.go.Figure", return_value=mock_fig),
patch("semantica.visualization.kg_visualizer.go.Scatter"),
patch("semantica.visualization.kg_visualizer.go.Layout"),
patch(
"semantica.visualization.kg_visualizer.ColorPalette.get_entity_type_colors",
return_value={"Person": "#ff0000"},
@@ -254,9 +243,12 @@ class TestAllVisualizeMethodsAcceptKGObject(unittest.TestCase):
self.viz._normalize_graph = MagicMock(return_value=GRAPH_DICT)
self.viz._visualize_network_plotly = MagicMock(return_value=MagicMock())
communities = {"node_assignments": {"e1": 0, "e2": 1}, "num_communities": 2}
with patch(
"semantica.visualization.kg_visualizer.ColorPalette.get_community_colors",
return_value=["#ff0000", "#00ff00"],
with (
plotly_doubles(kg_visualizer),
patch(
"semantica.visualization.kg_visualizer.ColorPalette.get_community_colors",
return_value=["#ff0000", "#00ff00"],
),
):
self.viz.visualize_communities(self.kg, communities=communities)
self.viz._normalize_graph.assert_called_once_with(self.kg)
@@ -264,22 +256,24 @@ class TestAllVisualizeMethodsAcceptKGObject(unittest.TestCase):
def test_visualize_centrality_accepts_kg_object(self):
self.viz._normalize_graph = MagicMock(return_value=GRAPH_DICT)
self.viz._visualize_network_plotly = MagicMock(return_value=MagicMock())
self.viz.visualize_centrality(self.kg, centrality={"centrality": {}})
with plotly_doubles(kg_visualizer):
self.viz.visualize_centrality(self.kg, centrality={"centrality": {}})
self.viz._normalize_graph.assert_called_once_with(self.kg)
def test_visualize_entity_types_accepts_kg_object(self):
self.viz._normalize_graph = MagicMock(return_value=GRAPH_DICT)
mock_px = sys.modules["plotly.express"]
mock_px.bar.return_value = MagicMock()
self.viz.visualize_entity_types(self.kg)
with plotly_doubles(kg_visualizer), patch("semantica.visualization.kg_visualizer.px.bar"):
self.viz.visualize_entity_types(self.kg)
self.viz._normalize_graph.assert_called_once_with(self.kg)
def test_visualize_relationship_matrix_accepts_kg_object(self):
self.viz._normalize_graph = MagicMock(return_value=GRAPH_DICT)
mock_go = sys.modules["plotly.graph_objects"]
mock_go.Figure.return_value = MagicMock()
mock_go.Heatmap.return_value = MagicMock()
self.viz.visualize_relationship_matrix(self.kg)
with (
plotly_doubles(kg_visualizer),
patch("semantica.visualization.kg_visualizer.go.Figure"),
patch("semantica.visualization.kg_visualizer.go.Heatmap"),
):
self.viz.visualize_relationship_matrix(self.kg)
self.viz._normalize_graph.assert_called_once_with(self.kg)
@@ -361,10 +355,6 @@ class TestFormalKnowledgeGraphType(unittest.TestCase):
def _run_visualize_network(self, graph_arg):
mock_fig = MagicMock()
mock_go = sys.modules["plotly.graph_objects"]
mock_go.Figure.return_value = mock_fig
mock_go.Scatter.return_value = MagicMock()
mock_go.Layout.return_value = MagicMock()
viz = _make_viz()
fake_pos = {"e1": (0.0, 0.0), "e2": (1.0, 1.0)}
viz.force_layout = MagicMock()
@@ -372,6 +362,10 @@ class TestFormalKnowledgeGraphType(unittest.TestCase):
viz.hierarchical_layout = MagicMock()
viz.circular_layout = MagicMock()
with (
plotly_doubles(kg_visualizer),
patch("semantica.visualization.kg_visualizer.go.Figure", return_value=mock_fig),
patch("semantica.visualization.kg_visualizer.go.Scatter"),
patch("semantica.visualization.kg_visualizer.go.Layout"),
patch(
"semantica.visualization.kg_visualizer.ColorPalette.get_entity_type_colors",
return_value={"Person": "#ff0000"},
@@ -392,9 +386,12 @@ class TestFormalKnowledgeGraphType(unittest.TestCase):
viz._normalize_graph = MagicMock(return_value=GRAPH_DICT)
viz._visualize_network_plotly = MagicMock(return_value=MagicMock())
communities = {"node_assignments": {"e1": 0, "e2": 1}, "num_communities": 2}
with patch(
"semantica.visualization.kg_visualizer.ColorPalette.get_community_colors",
return_value=["#ff0000", "#00ff00"],
with (
plotly_doubles(kg_visualizer),
patch(
"semantica.visualization.kg_visualizer.ColorPalette.get_community_colors",
return_value=["#ff0000", "#00ff00"],
),
):
viz.visualize_communities(kg, communities=communities)
viz._normalize_graph.assert_called_once_with(kg)
@@ -404,24 +401,28 @@ class TestFormalKnowledgeGraphType(unittest.TestCase):
viz = _make_viz()
viz._normalize_graph = MagicMock(return_value=GRAPH_DICT)
viz._visualize_network_plotly = MagicMock(return_value=MagicMock())
viz.visualize_centrality(kg, centrality={"centrality": {}})
with plotly_doubles(kg_visualizer):
viz.visualize_centrality(kg, centrality={"centrality": {}})
viz._normalize_graph.assert_called_once_with(kg)
def test_visualize_entity_types_accepts_knowledge_graph(self):
kg = self._make_kg()
viz = _make_viz()
viz._normalize_graph = MagicMock(return_value=GRAPH_DICT)
sys.modules["plotly.express"].bar.return_value = MagicMock()
viz.visualize_entity_types(kg)
with plotly_doubles(kg_visualizer), patch("semantica.visualization.kg_visualizer.px.bar"):
viz.visualize_entity_types(kg)
viz._normalize_graph.assert_called_once_with(kg)
def test_visualize_relationship_matrix_accepts_knowledge_graph(self):
kg = self._make_kg()
viz = _make_viz()
viz._normalize_graph = MagicMock(return_value=GRAPH_DICT)
sys.modules["plotly.graph_objects"].Figure.return_value = MagicMock()
sys.modules["plotly.graph_objects"].Heatmap.return_value = MagicMock()
viz.visualize_relationship_matrix(kg)
with (
plotly_doubles(kg_visualizer),
patch("semantica.visualization.kg_visualizer.go.Figure"),
patch("semantica.visualization.kg_visualizer.go.Heatmap"),
):
viz.visualize_relationship_matrix(kg)
viz._normalize_graph.assert_called_once_with(kg)
def test_knowledge_graph_importable_from_kg_module(self):
+77 -111
View File
@@ -1,149 +1,115 @@
import unittest
from unittest.mock import MagicMock, patch
import importlib
import sys
import unittest
from contextlib import contextmanager
from unittest.mock import patch
import numpy as np
# Helper to mock modules
def mock_module(name):
m = MagicMock()
sys.modules[name] = m
return m
from tests.visualization._plotly_doubles import plotly_doubles
@contextmanager
def import_without(module_name, *dependencies):
"""Import a module with selected optional dependencies unavailable."""
package_name, attribute = module_name.rsplit(".", 1)
package = importlib.import_module(package_name)
missing = object()
original_module = sys.modules.pop(module_name, missing)
original_attribute = getattr(package, attribute, missing)
try:
with patch.dict(sys.modules, {name: None for name in dependencies}):
yield importlib.import_module(module_name)
finally:
sys.modules.pop(module_name, None)
if original_module is not missing:
sys.modules[module_name] = original_module
if original_attribute is missing:
package.__dict__.pop(attribute, None)
else:
setattr(package, attribute, original_attribute)
class TestOptionalDependencies(unittest.TestCase):
@classmethod
def setUpClass(cls):
# Mock heavy/problematic dependencies globally to prevent environment crashes
# We use a dict to save original modules if they exist, but for this test file
# we generally want to run in a controlled "clean" environment.
cls.modules_to_patch = [
'sklearn', 'sklearn.decomposition', 'sklearn.manifold',
'scipy', 'scipy.optimize',
'matplotlib', 'matplotlib.pyplot', 'matplotlib.patches',
'plotly', 'plotly.express', 'plotly.graph_objects', 'plotly.subplots',
'networkx', 'seaborn'
]
cls.original_modules = {}
for mod in cls.modules_to_patch:
if mod in sys.modules:
cls.original_modules[mod] = sys.modules[mod]
sys.modules[mod] = MagicMock()
@classmethod
def tearDownClass(cls):
# Restore original modules
for mod in cls.modules_to_patch:
if mod in cls.original_modules:
sys.modules[mod] = cls.original_modules[mod]
else:
del sys.modules[mod]
def setUp(self):
# Clear cached visualization modules to ensure fresh imports
self.viz_modules = [
'semantica.visualization.embedding_visualizer',
'semantica.visualization.ontology_visualizer',
'semantica.visualization.kg_visualizer',
'semantica.visualization.utils.export_formats'
]
for mod in self.viz_modules:
if mod in sys.modules:
del sys.modules[mod]
def test_embedding_visualizer_without_umap(self):
"""Test EmbeddingVisualizer behavior when umap is missing."""
# Ensure umap is missing
with patch.dict(sys.modules, {'umap': None}):
from semantica.visualization.embedding_visualizer import EmbeddingVisualizer
# Setup PCA mock to verify fallback
mock_pca_class = sys.modules['sklearn.decomposition'].PCA
mock_pca_instance = mock_pca_class.return_value
# Configure fit_transform to return correct shape (n_samples, 2)
mock_pca_instance.fit_transform.return_value = np.zeros((4, 2))
viz = EmbeddingVisualizer()
# Use numpy array!
embeddings = np.array([[0, 1, 2], [1, 0, 3], [0, 0, 0], [1, 1, 1]])
# Should fallback to PCA when method="umap" is used but umap is None
# The code logs a warning and uses PCA
viz.visualize_2d_projection(embeddings, method="umap")
# Verify PCA was called
with import_without(
"semantica.visualization.embedding_visualizer", "umap"
) as module:
with plotly_doubles(module), patch.object(module, "PCA") as mock_pca_class:
mock_pca_class.return_value.fit_transform.return_value = np.zeros((4, 2))
viz = module.EmbeddingVisualizer()
embeddings = np.array([[0, 1, 2], [1, 0, 3], [0, 0, 0], [1, 1, 1]])
viz.visualize_2d_projection(embeddings, method="umap")
mock_pca_class.assert_called()
def test_ontology_visualizer_without_graphviz(self):
"""Test OntologyVisualizer behavior when graphviz is missing."""
# Ensure graphviz is missing
with patch.dict(sys.modules, {'graphviz': None}):
from semantica.visualization.ontology_visualizer import OntologyVisualizer, ProcessingError
viz = OntologyVisualizer()
with import_without(
"semantica.visualization.ontology_visualizer", "graphviz"
) as module:
viz = module.OntologyVisualizer()
ontology = {
"classes": [
{"name": "A", "label": "A"},
{"name": "B", "label": "B", "parent": "A"}
{"name": "B", "label": "B", "parent": "A"},
]
}
with self.assertRaises(ProcessingError) as cm:
with self.assertRaises(module.ProcessingError) as cm:
viz.visualize_hierarchy(ontology, output="dot", file_path="test.dot")
self.assertIn("Graphviz is required for DOT export", str(cm.exception))
def test_analytics_visualizer_without_plotly(self):
"""Test AnalyticsVisualizer behavior when plotly is missing."""
with patch.dict(sys.modules, {'plotly': None, 'plotly.express': None, 'plotly.graph_objects': None}):
from semantica.visualization.analytics_visualizer import AnalyticsVisualizer, ProcessingError
# Need to ensure numpy is available for init (it's imported at top level)
# But we are testing plotly missing.
viz = AnalyticsVisualizer()
with self.assertRaises(ProcessingError) as cm:
viz.visualize_centrality_rankings({"node1": 1.0})
self.assertIn("Plotly is required", str(cm.exception))
with import_without(
"semantica.visualization.analytics_visualizer",
"plotly",
"plotly.express",
"plotly.graph_objects",
) as module:
viz = module.AnalyticsVisualizer()
def test_analytics_visualizer_without_plotly(self):
"""Test AnalyticsVisualizer behavior when plotly is missing."""
with patch.dict(sys.modules, {'plotly': None, 'plotly.express': None, 'plotly.graph_objects': None}):
from semantica.visualization.analytics_visualizer import AnalyticsVisualizer, ProcessingError
viz = AnalyticsVisualizer()
with self.assertRaises(ProcessingError) as cm:
with self.assertRaises(module.ProcessingError) as cm:
viz.visualize_centrality_rankings({})
self.assertIn("Plotly is required", str(cm.exception))
def test_semantic_network_visualizer_without_plotly(self):
"""Test SemanticNetworkVisualizer behavior when plotly is missing."""
with patch.dict(sys.modules, {'plotly': None, 'plotly.express': None, 'plotly.graph_objects': None}):
from semantica.visualization.semantic_network_visualizer import SemanticNetworkVisualizer, ProcessingError
viz = SemanticNetworkVisualizer()
with self.assertRaises(ProcessingError) as cm:
with import_without(
"semantica.visualization.semantic_network_visualizer",
"plotly",
"plotly.express",
"plotly.graph_objects",
) as module:
viz = module.SemanticNetworkVisualizer()
with self.assertRaises(module.ProcessingError) as cm:
viz.visualize_network({})
self.assertIn("Plotly is required", str(cm.exception))
def test_temporal_visualizer_without_plotly(self):
"""Test TemporalVisualizer behavior when plotly is missing."""
with patch.dict(sys.modules, {'plotly': None, 'plotly.express': None, 'plotly.graph_objects': None}):
from semantica.visualization.temporal_visualizer import TemporalVisualizer, ProcessingError
viz = TemporalVisualizer()
with self.assertRaises(ProcessingError) as cm:
with import_without(
"semantica.visualization.temporal_visualizer",
"plotly",
"plotly.express",
"plotly.graph_objects",
) as module:
viz = module.TemporalVisualizer()
with self.assertRaises(module.ProcessingError) as cm:
viz.visualize_timeline({"events": []})
self.assertIn("Plotly is required", str(cm.exception))
if __name__ == '__main__':
if __name__ == "__main__":
unittest.main()
+1 -23
View File
@@ -1,27 +1,5 @@
import unittest
from unittest.mock import MagicMock, patch, ANY
import sys
import types
# Helper to create a mock package
def mock_package(name):
m = MagicMock()
m.__path__ = []
sys.modules[name] = m
return m
# Mock libraries before importing module under test
# We need to ensure matplotlib behaves like a package for seaborn
sys.modules['matplotlib'] = MagicMock()
sys.modules['matplotlib.colors'] = MagicMock()
sys.modules['matplotlib.pyplot'] = MagicMock()
sys.modules['matplotlib.patches'] = MagicMock()
sys.modules['plotly'] = MagicMock()
sys.modules['plotly.express'] = MagicMock()
sys.modules['plotly.graph_objects'] = MagicMock()
sys.modules['plotly.subplots'] = MagicMock()
sys.modules['graphviz'] = MagicMock()
sys.modules['seaborn'] = MagicMock()
from unittest.mock import MagicMock, patch
from semantica.visualization.kg_visualizer import KGVisualizer
from semantica.visualization.ontology_visualizer import OntologyVisualizer
@@ -1,34 +1,25 @@
import unittest
from contextlib import ExitStack
from unittest.mock import MagicMock, patch
import sys
import numpy as np
# Mock heavy libraries before importing visualization modules
sys.modules['matplotlib'] = MagicMock()
sys.modules['matplotlib.pyplot'] = MagicMock()
sys.modules['matplotlib.colors'] = MagicMock()
sys.modules['matplotlib.patches'] = MagicMock()
sys.modules['plotly'] = MagicMock()
sys.modules['plotly.express'] = MagicMock()
sys.modules['plotly.graph_objects'] = MagicMock()
sys.modules['plotly.subplots'] = MagicMock()
sys.modules['seaborn'] = MagicMock()
sys.modules['umap'] = MagicMock()
sys.modules['sklearn'] = MagicMock()
sys.modules['sklearn.decomposition'] = MagicMock()
sys.modules['sklearn.manifold'] = MagicMock()
from semantica.visualization import analytics_visualizer, embedding_visualizer
from semantica.visualization.analytics_visualizer import AnalyticsVisualizer
from semantica.visualization.embedding_visualizer import EmbeddingVisualizer
from semantica.visualization.utils.color_schemes import ColorScheme
from tests.visualization._plotly_doubles import plotly_doubles
class TestVisualizationAdvanced(unittest.TestCase):
def setUp(self):
self.mock_logger = MagicMock()
self.mock_tracker = MagicMock()
stack = ExitStack()
self.addCleanup(stack.close)
stack.enter_context(plotly_doubles(analytics_visualizer, embedding_visualizer))
self.patchers = [
patch('semantica.visualization.analytics_visualizer.get_logger', return_value=self.mock_logger),
patch('semantica.visualization.analytics_visualizer.get_progress_tracker', return_value=self.mock_tracker),
@@ -53,22 +44,17 @@ class TestVisualizationAdvanced(unittest.TestCase):
viz = AnalyticsVisualizer()
centrality = {"n1": 0.5, "n2": 0.3}
# Access the mock that was injected
import plotly.graph_objects as go
# Reset mock to ensure clean state
go.Bar.reset_mock()
viz.visualize_centrality_rankings(centrality, output="interactive")
go.Bar.assert_called()
with (
patch('semantica.visualization.analytics_visualizer.go.Bar') as mock_bar,
patch('semantica.visualization.analytics_visualizer.go.Figure'),
):
viz.visualize_centrality_rankings(centrality, output="interactive")
mock_bar.assert_called()
def test_visualize_community_structure(self):
viz = AnalyticsVisualizer()
if hasattr(viz, 'visualize_community_structure'):
import plotly.graph_objects as go
# Reset mocks
go.Figure.reset_mock()
graph = MagicMock()
communities = {"c1": ["n1", "n2"]}
@@ -89,8 +75,6 @@ class TestVisualizationAdvanced(unittest.TestCase):
viz = EmbeddingVisualizer()
embeddings = np.random.rand(10, 128)
import plotly.graph_objects as go
# Mock UMAP/TSNE/PCA
with patch('semantica.visualization.embedding_visualizer.umap') as mock_umap, \
patch('semantica.visualization.embedding_visualizer.TSNE') as mock_tsne, \
@@ -116,12 +100,13 @@ class TestVisualizationAdvanced(unittest.TestCase):
viz = EmbeddingVisualizer()
embeddings = np.random.rand(5, 5)
import plotly.graph_objects as go
go.Heatmap.reset_mock()
if hasattr(viz, 'visualize_similarity_heatmap'):
viz.visualize_similarity_heatmap(embeddings)
go.Heatmap.assert_called()
with (
patch('semantica.visualization.embedding_visualizer.go.Heatmap') as mock_heatmap,
patch('semantica.visualization.embedding_visualizer.go.Figure'),
):
viz.visualize_similarity_heatmap(embeddings)
mock_heatmap.assert_called()
if __name__ == '__main__':
unittest.main()
@@ -1,26 +1,9 @@
import unittest
from unittest.mock import MagicMock, patch
import sys
import numpy as np
from pathlib import Path
import pytest
# Mock heavy libraries before importing visualization modules
sys.modules['matplotlib'] = MagicMock()
sys.modules['matplotlib.pyplot'] = MagicMock()
sys.modules['matplotlib.colors'] = MagicMock()
sys.modules['matplotlib.patches'] = MagicMock()
sys.modules['plotly'] = MagicMock()
sys.modules['plotly.express'] = MagicMock()
sys.modules['plotly.graph_objects'] = MagicMock()
sys.modules['plotly.subplots'] = MagicMock()
sys.modules['seaborn'] = MagicMock()
sys.modules['umap'] = MagicMock()
sys.modules['sklearn'] = MagicMock()
sys.modules['sklearn.decomposition'] = MagicMock()
sys.modules['sklearn.manifold'] = MagicMock()
sys.modules['networkx'] = MagicMock()
sys.modules['graphviz'] = MagicMock()
# Import visualizers
from semantica.visualization.kg_visualizer import KGVisualizer
@@ -52,24 +35,24 @@ class TestVisualizationComprehensive(unittest.TestCase):
patch('semantica.visualization.analytics_visualizer.get_progress_tracker', return_value=self.mock_tracker),
patch('semantica.visualization.temporal_visualizer.get_logger', return_value=self.mock_logger),
patch('semantica.visualization.temporal_visualizer.get_progress_tracker', return_value=self.mock_tracker),
# Mock Layouts
patch('semantica.visualization.kg_visualizer.ForceDirectedLayout', MagicMock()),
patch('semantica.visualization.kg_visualizer.HierarchicalLayout', MagicMock()),
patch('semantica.visualization.kg_visualizer.CircularLayout', MagicMock()),
patch('semantica.visualization.ontology_visualizer.HierarchicalLayout', MagicMock()),
patch('semantica.visualization.semantic_network_visualizer.ForceDirectedLayout', MagicMock()),
patch('semantica.visualization.kg_visualizer.go', MagicMock()),
patch('semantica.visualization.kg_visualizer.px', MagicMock()),
patch('semantica.visualization.ontology_visualizer.go', MagicMock()),
patch('semantica.visualization.ontology_visualizer.make_subplots', MagicMock()),
patch('semantica.visualization.embedding_visualizer.go', MagicMock()),
patch('semantica.visualization.embedding_visualizer.px', MagicMock()),
patch('semantica.visualization.semantic_network_visualizer.go', MagicMock()),
patch('semantica.visualization.semantic_network_visualizer.px', MagicMock()),
patch('semantica.visualization.analytics_visualizer.go', MagicMock()),
patch('semantica.visualization.analytics_visualizer.px', MagicMock()),
patch('semantica.visualization.analytics_visualizer.make_subplots', MagicMock()),
patch('semantica.visualization.temporal_visualizer.go', MagicMock()),
patch('semantica.visualization.temporal_visualizer.px', MagicMock()),
]
for p in self.patchers:
p.start()
# Reset plotly mocks
import plotly.graph_objects as go
import plotly.express as px
go.Figure.reset_mock()
px.bar.reset_mock()
px.scatter.reset_mock()
def tearDown(self):
for p in self.patchers:
p.stop()
@@ -210,8 +193,8 @@ class TestVisualizationComprehensive(unittest.TestCase):
embeddings = np.random.rand(10, 10)
# Test visualize_2d_projection (mock UMAP/PCA)
with patch('semantica.visualization.embedding_visualizer.umap.UMAP') as MockUMAP:
MockUMAP.return_value.fit_transform.return_value = np.random.rand(10, 2)
with patch('semantica.visualization.embedding_visualizer.umap', MagicMock()) as mock_umap:
mock_umap.UMAP.return_value.fit_transform.return_value = np.random.rand(10, 2)
viz.visualize_2d_projection(embeddings)
# Test visualize_similarity_heatmap
@@ -219,8 +202,8 @@ class TestVisualizationComprehensive(unittest.TestCase):
# Test visualize_clustering
clusters = [0, 1, 0, 1, 0, 1, 0, 1, 0, 1]
with patch('semantica.visualization.embedding_visualizer.umap.UMAP') as MockUMAP:
MockUMAP.return_value.fit_transform.return_value = np.random.rand(10, 2)
with patch('semantica.visualization.embedding_visualizer.umap', MagicMock()) as mock_umap:
mock_umap.UMAP.return_value.fit_transform.return_value = np.random.rand(10, 2)
viz.visualize_clustering(embeddings, clusters)
if __name__ == '__main__':