Skip to content

Commit 9dc0b1c

Browse files
Merge branch 'codex/fully-test-and-review-code'
Add async test runner and guard optional RL dependencies - Added conftest.py with async test configuration - Added pytest.skip for optional gymnasium dependency - Improved test reliability with proper dependency checks - Enhanced test runner compatibility with pytest-asyncio 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2 parents a9502fe + 7bae678 commit 9dc0b1c

File tree

7 files changed

+85
-41
lines changed

7 files changed

+85
-41
lines changed

conftest.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
"""Pytest configuration for Mujoco MCP tests."""
2+
3+
from __future__ import annotations
4+
5+
import asyncio
6+
import inspect
7+
8+
import pytest
9+
10+
11+
@pytest.hookimpl(tryfirst=True)
12+
def pytest_pyfunc_call(pyfuncitem: pytest.Item) -> bool | None:
13+
"""Allow ``async def`` tests to run without pytest-asyncio."""
14+
test_func = getattr(pyfuncitem, "obj", None)
15+
if inspect.iscoroutinefunction(test_func):
16+
asyncio.run(test_func(**pyfuncitem.funcargs))
17+
return True
18+
return None

tests/integration/test_advanced_features.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
Tests all new capabilities: controllers, coordination, sensors, RL, benchmarks, visualization
55
"""
66

7+
import importlib.util
78
import time
89
import numpy as np
910
import sys
@@ -12,11 +13,23 @@
1213
import tempfile
1314
import json
1415

16+
import pytest
17+
1518
# Add project to path
1619
REPO_ROOT = Path(__file__).resolve().parents[2]
1720
sys.path.insert(0, str(REPO_ROOT / "src"))
1821
sys.path.insert(0, str(REPO_ROOT))
1922

23+
missing_optional = [
24+
name for name in ("scipy", "gymnasium") if importlib.util.find_spec(name) is None
25+
]
26+
27+
if missing_optional:
28+
pytest.skip(
29+
"Missing optional dependencies: " + ", ".join(missing_optional),
30+
allow_module_level=True,
31+
)
32+
2033
# Import all advanced modules
2134
from mujoco_mcp.advanced_controllers import (
2235
PIDController,

tests/integration/test_debug.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,21 @@
11
#!/usr/bin/env python3
22
"""Debug the action space issue"""
33

4+
import importlib.util
45
import sys
56
from pathlib import Path
67
import numpy as np
78

9+
import pytest
10+
811
# Add src to path for imports
912
REPO_ROOT = Path(__file__).resolve().parents[2]
1013
sys.path.insert(0, str(REPO_ROOT / "src"))
1114
sys.path.insert(0, str(REPO_ROOT))
1215

16+
if importlib.util.find_spec("gymnasium") is None:
17+
pytest.skip("gymnasium is required for RL integration tests", allow_module_level=True)
18+
1319
from mujoco_mcp.rl_integration import create_balancing_env
1420

1521

tests/rl/test_rl_advanced.py

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,27 +4,29 @@
44
Tests policy evaluation, training workflows, and advanced RL features
55
"""
66

7+
import importlib.util
78
import sys
89
import time
910
import numpy as np
1011
import json
1112
from pathlib import Path
1213
from typing import Dict, Any
1314

15+
import pytest
16+
1417
# Add src to path for imports
1518
REPO_ROOT = Path(__file__).resolve().parents[2]
1619
sys.path.insert(0, str(REPO_ROOT / "src"))
1720
sys.path.insert(0, str(REPO_ROOT))
1821

19-
try:
20-
from mujoco_mcp.rl_integration import (
21-
RLConfig, MuJoCoRLEnvironment, RLTrainer,
22-
ReachingTaskReward, BalancingTaskReward, WalkingTaskReward,
23-
create_reaching_env, create_balancing_env, create_walking_env
24-
)
25-
except ImportError as e:
26-
print(f"❌ Import Error: {e}")
27-
sys.exit(1)
22+
if importlib.util.find_spec("gymnasium") is None:
23+
pytest.skip("gymnasium is required for RL integration tests", allow_module_level=True)
24+
25+
from mujoco_mcp.rl_integration import (
26+
RLConfig, MuJoCoRLEnvironment, RLTrainer,
27+
ReachingTaskReward, BalancingTaskReward, WalkingTaskReward,
28+
create_reaching_env, create_balancing_env, create_walking_env
29+
)
2830

2931
class AdvancedRLTests:
3032
"""Advanced RL functionality tests"""

tests/rl/test_rl_functionality.py

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,31 +4,32 @@
44
Tests all aspects of the MuJoCo MCP RL integration
55
"""
66

7+
import importlib.util
78
import sys
89
import time
910
import numpy as np
1011
import logging
1112
from pathlib import Path
1213
from typing import Dict, Any
1314

15+
import pytest
16+
1417
# Add src to path for imports
1518
REPO_ROOT = Path(__file__).resolve().parents[2]
1619
sys.path.insert(0, str(REPO_ROOT / "src"))
1720
sys.path.insert(0, str(REPO_ROOT))
1821

19-
try:
20-
from mujoco_mcp.rl_integration import (
21-
RLConfig, MuJoCoRLEnvironment, RLTrainer,
22-
ReachingTaskReward, BalancingTaskReward, WalkingTaskReward,
23-
create_reaching_env, create_balancing_env, create_walking_env,
24-
example_training
25-
)
26-
from mujoco_mcp.viewer_client import MuJoCoViewerClient
27-
from mujoco_mcp.simulation import MuJoCoSimulation
28-
except ImportError as e:
29-
print(f"❌ Import Error: {e}")
30-
print("Make sure MuJoCo MCP is properly installed")
31-
sys.exit(1)
22+
if importlib.util.find_spec("gymnasium") is None:
23+
pytest.skip("gymnasium is required for RL integration tests", allow_module_level=True)
24+
25+
from mujoco_mcp.rl_integration import (
26+
RLConfig, MuJoCoRLEnvironment, RLTrainer,
27+
ReachingTaskReward, BalancingTaskReward, WalkingTaskReward,
28+
create_reaching_env, create_balancing_env, create_walking_env,
29+
example_training
30+
)
31+
from mujoco_mcp.viewer_client import MuJoCoViewerClient
32+
from mujoco_mcp.simulation import MuJoCoSimulation
3233

3334
# Configure logging
3435
logging.basicConfig(level=logging.INFO)

tests/rl/test_rl_integration.py

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
Tests RL functionality with actual MuJoCo physics simulation
55
"""
66

7+
import importlib.util
78
import sys
89
import time
910
import subprocess
@@ -15,21 +16,22 @@
1516
import threading
1617
import logging
1718

19+
import pytest
20+
1821
# Add src to path for imports
1922
REPO_ROOT = Path(__file__).resolve().parents[2]
2023
sys.path.insert(0, str(REPO_ROOT / "src"))
2124
sys.path.insert(0, str(REPO_ROOT))
2225

23-
try:
24-
from mujoco_mcp.rl_integration import (
25-
RLConfig, MuJoCoRLEnvironment, RLTrainer,
26-
create_reaching_env, create_balancing_env, create_walking_env
27-
)
28-
from mujoco_mcp.viewer_server import MuJoCoViewerServer
29-
from mujoco_mcp.viewer_client import MuJoCoViewerClient
30-
except ImportError as e:
31-
print(f"❌ Import Error: {e}")
32-
sys.exit(1)
26+
if importlib.util.find_spec("gymnasium") is None:
27+
pytest.skip("gymnasium is required for RL integration tests", allow_module_level=True)
28+
29+
from mujoco_mcp.rl_integration import (
30+
RLConfig, MuJoCoRLEnvironment, RLTrainer,
31+
create_reaching_env, create_balancing_env, create_walking_env
32+
)
33+
from mujoco_mcp.viewer_server import MuJoCoViewerServer
34+
from mujoco_mcp.viewer_client import MuJoCoViewerClient
3335

3436
class RLIntegrationTest:
3537
"""Test RL integration with MuJoCo viewer"""

tests/rl/test_rl_simple.py

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,27 @@
33
Simplified RL Test - Tests core RL functionality without MuJoCo viewer dependency
44
"""
55

6+
import importlib.util
67
import sys
78
import time
89
import numpy as np
910
from pathlib import Path
1011

12+
import pytest
13+
1114
# Add src to path for imports
1215
REPO_ROOT = Path(__file__).resolve().parents[2]
1316
sys.path.insert(0, str(REPO_ROOT / "src"))
1417
sys.path.insert(0, str(REPO_ROOT))
1518

16-
try:
17-
from mujoco_mcp.rl_integration import (
18-
RLConfig, MuJoCoRLEnvironment, RLTrainer,
19-
create_reaching_env, create_balancing_env, create_walking_env,
20-
example_training
21-
)
22-
except ImportError as e:
23-
print(f"❌ Import Error: {e}")
24-
sys.exit(1)
19+
if importlib.util.find_spec("gymnasium") is None:
20+
pytest.skip("gymnasium is required for RL integration tests", allow_module_level=True)
21+
22+
from mujoco_mcp.rl_integration import (
23+
RLConfig, MuJoCoRLEnvironment, RLTrainer,
24+
create_reaching_env, create_balancing_env, create_walking_env,
25+
example_training
26+
)
2527

2628
def test_rl_core_functionality():
2729
"""Test core RL functionality without MuJoCo viewer"""

0 commit comments

Comments
 (0)