-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathtest_environment_dependencies.py
More file actions
265 lines (210 loc) · 8.29 KB
/
test_environment_dependencies.py
File metadata and controls
265 lines (210 loc) · 8.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
#!/usr/bin/env python3
"""
Test Environment Dependencies - Tests for environment dependency management.
Tests verification and management of Python package dependencies.
"""
import sys
from pathlib import Path
import pytest
# Add src to path for imports
sys.path.insert(0, str(Path(__file__).parent.parent))
class TestCoreDependencies:
"""Tests for core Python dependencies."""
@pytest.mark.fast
def test_numpy_available(self):
"""Test NumPy is installed and functional."""
import numpy as np
# Basic functionality test
arr = np.array([1, 2, 3])
assert arr.shape == (3,)
assert np.sum(arr) == 6
@pytest.mark.fast
def test_pathlib_available(self):
"""Test pathlib is available (stdlib)."""
from pathlib import Path
p = Path(".")
assert p.exists()
@pytest.mark.fast
def test_json_available(self):
"""Test json is available (stdlib)."""
import json
data = {"key": "value"}
encoded = json.dumps(data)
decoded = json.loads(encoded)
assert decoded == data
@pytest.mark.fast
def test_logging_available(self):
"""Test logging is available (stdlib)."""
import logging
logger = logging.getLogger("test")
assert logger is not None
class TestVisualizationDependencies:
"""Tests for visualization dependencies."""
@pytest.mark.fast
def test_matplotlib_available(self):
"""Test matplotlib is installed."""
try:
import matplotlib
import matplotlib.pyplot as plt
assert hasattr(matplotlib, '__version__'), "matplotlib missing __version__"
assert hasattr(plt, 'figure'), "matplotlib.pyplot missing figure function"
except ImportError:
pytest.skip("matplotlib not installed")
@pytest.mark.fast
def test_seaborn_available(self):
"""Test seaborn is installed."""
try:
import seaborn as sns
assert hasattr(sns, '__version__'), "seaborn missing __version__"
assert hasattr(sns, 'set_theme'), "seaborn missing set_theme function"
except ImportError:
pytest.skip("seaborn not installed")
class TestAudioDependencies:
"""Tests for audio processing dependencies."""
@pytest.mark.fast
def test_audio_backends(self):
"""Test audio backend availability."""
from audio import check_audio_backends
backends = check_audio_backends()
assert isinstance(backends, dict)
assert 'numpy' in backends
# NumPy is core and should always be available
assert backends['numpy']['available'] is True
@pytest.mark.fast
def test_librosa_availability(self):
"""Test librosa availability."""
try:
import librosa
assert hasattr(librosa, '__version__')
except ImportError:
pytest.skip("librosa not installed")
@pytest.mark.fast
def test_soundfile_availability(self):
"""Test soundfile availability."""
try:
import soundfile
assert hasattr(soundfile, '__version__')
except ImportError:
pytest.skip("soundfile not installed")
class TestMLDependencies:
"""Tests for machine learning dependencies."""
@pytest.mark.fast
def test_scipy_available(self):
"""Test scipy is installed."""
try:
import scipy
assert hasattr(scipy, '__version__')
except ImportError:
pytest.skip("scipy not installed")
@pytest.mark.fast
def test_pymdp_available(self):
"""Test pymdp is installed for Active Inference."""
try:
# Try inferactively-pymdp first (preferred)
try:
from pymdp.agent import Agent
assert Agent is not None
return
except ImportError:
pass
# Recovery to previous pymdp API
import pymdp
assert hasattr(pymdp, 'MDP') or hasattr(pymdp, 'mdp') or hasattr(pymdp, '__version__'), \
"pymdp missing expected attributes"
except ImportError:
pytest.skip("pymdp not installed")
class TestDependencyVersions:
"""Tests for dependency version requirements."""
@pytest.mark.fast
def test_python_version(self):
"""Test Python version meets requirements."""
import sys
# Require Python 3.9+
assert sys.version_info >= (3, 9)
@pytest.mark.fast
def test_numpy_version(self):
"""Test NumPy version."""
import numpy as np
version_parts = np.__version__.split('.')
major = int(version_parts[0])
# Require NumPy 1.x or 2.x
assert major >= 1
class TestDependencyConflicts:
"""Tests for dependency conflict detection."""
@pytest.mark.fast
def test_no_import_conflicts(self):
"""Test core imports don't conflict."""
# Import in specific order to detect conflicts
import json
import logging
from pathlib import Path
import numpy as np
# Verify each module is functional after imports
assert json.dumps({"test": 1}) == '{"test": 1}'
assert logging.getLogger("test") is not None
assert Path(".").exists()
assert np.array([1, 2, 3]).sum() == 6
@pytest.mark.fast
def test_visualization_imports_compatible(self):
"""Test visualization imports are compatible."""
try:
import matplotlib
matplotlib.use('Agg') # Non-interactive backend
import matplotlib.pyplot as plt
# Basic compatibility test
fig, ax = plt.subplots()
line_objs = ax.plot([1, 2, 3])
assert len(line_objs) == 1, "Expected one line object from plot"
assert fig is not None, "Figure should be created"
plt.close(fig)
except Exception as e:
pytest.skip(f"Visualization compatibility issue: {e}")
class TestOptionalDependencies:
"""Tests for optional dependency handling."""
@pytest.mark.fast
def test_optional_deps_graceful_import(self):
"""Test optional dependencies fail gracefully."""
# This pattern should be used throughout codebase
try:
import nonexistent_package
available = True
except ImportError:
available = False
assert available is False
@pytest.mark.fast
def test_feature_flags_reflect_deps(self):
"""Test feature flags reflect dependency availability."""
from audio import FEATURES, check_audio_backends
check_audio_backends()
# Features should be consistent with backends
assert isinstance(FEATURES, dict)
class TestDependencyDiscovery:
"""Tests for dependency discovery functionality."""
@pytest.mark.fast
def test_list_installed_packages(self):
"""Test we can list installed packages."""
# Use importlib.metadata (Python 3.10+) or recovery to uv
try:
from importlib.metadata import distributions
packages = [d.metadata['Name'] for d in distributions()]
assert len(packages) > 0
except ImportError:
# Recovery to uv pip list for uv-managed environments
import subprocess # nosec B404 -- subprocess calls with controlled/trusted input
result = subprocess.run( # nosec B607 B603 -- subprocess calls with controlled/trusted input
['uv', 'pip', 'list', '--format=freeze'],
capture_output=True,
text=True,
cwd=str(Path(__file__).parent.parent.parent)
)
# Either stdout has content OR we skip (uv not available)
if result.returncode != 0 or len(result.stdout) == 0:
pytest.skip("Could not list packages via importlib.metadata or uv")
assert len(result.stdout) > 0
@pytest.mark.fast
def test_pyproject_toml_exists(self):
"""Test pyproject.toml dependency file exists (uv-managed)."""
from pathlib import Path
# GNN uses pyproject.toml exclusively for dependency management via uv
pyproject = Path(__file__).parent.parent.parent / "pyproject.toml"
assert pyproject.exists(), "pyproject.toml must exist for uv-managed dependencies"