diff --git a/conftest.py b/conftest.py new file mode 100644 index 0000000..0aac78a --- /dev/null +++ b/conftest.py @@ -0,0 +1,18 @@ +"""Pytest configuration for Mujoco MCP tests.""" + +from __future__ import annotations + +import asyncio +import inspect + +import pytest + + +@pytest.hookimpl(tryfirst=True) +def pytest_pyfunc_call(pyfuncitem: pytest.Item) -> bool | None: + """Allow ``async def`` tests to run without pytest-asyncio.""" + test_func = getattr(pyfuncitem, "obj", None) + if inspect.iscoroutinefunction(test_func): + asyncio.run(test_func(**pyfuncitem.funcargs)) + return True + return None diff --git a/test_advanced_features.py b/test_advanced_features.py index dd9137e..e923650 100644 --- a/test_advanced_features.py +++ b/test_advanced_features.py @@ -4,6 +4,7 @@ Tests all new capabilities: controllers, coordination, sensors, RL, benchmarks, visualization """ +import importlib.util import time import numpy as np import sys @@ -12,9 +13,21 @@ import tempfile import json +import pytest + # Add project to path sys.path.insert(0, str(Path(__file__).parent / "src")) +missing_optional = [ + name for name in ("scipy", "gymnasium") if importlib.util.find_spec(name) is None +] + +if missing_optional: + pytest.skip( + "Missing optional dependencies: " + ", ".join(missing_optional), + allow_module_level=True, + ) + # Import all advanced modules from mujoco_mcp.advanced_controllers import ( PIDController, diff --git a/test_debug.py b/test_debug.py index 575cd7b..60ecb41 100644 --- a/test_debug.py +++ b/test_debug.py @@ -1,13 +1,19 @@ #!/usr/bin/env python3 """Debug the action space issue""" +import importlib.util import sys from pathlib import Path import numpy as np +import pytest + # Add src to path for imports sys.path.insert(0, str(Path(__file__).parent / "src")) +if importlib.util.find_spec("gymnasium") is None: + pytest.skip("gymnasium is required for RL integration tests", allow_module_level=True) + from mujoco_mcp.rl_integration import create_balancing_env diff --git a/test_rl_advanced.py b/test_rl_advanced.py index dc57480..1602083 100644 --- a/test_rl_advanced.py +++ b/test_rl_advanced.py @@ -4,6 +4,7 @@ Tests policy evaluation, training workflows, and advanced RL features """ +import importlib.util import sys import time import numpy as np @@ -11,18 +12,19 @@ from pathlib import Path from typing import Dict, Any +import pytest + # Add src to path for imports sys.path.insert(0, str(Path(__file__).parent / "src")) -try: - from mujoco_mcp.rl_integration import ( - RLConfig, MuJoCoRLEnvironment, RLTrainer, - ReachingTaskReward, BalancingTaskReward, WalkingTaskReward, - create_reaching_env, create_balancing_env, create_walking_env - ) -except ImportError as e: - print(f"❌ Import Error: {e}") - sys.exit(1) +if importlib.util.find_spec("gymnasium") is None: + pytest.skip("gymnasium is required for RL integration tests", allow_module_level=True) + +from mujoco_mcp.rl_integration import ( + RLConfig, MuJoCoRLEnvironment, RLTrainer, + ReachingTaskReward, BalancingTaskReward, WalkingTaskReward, + create_reaching_env, create_balancing_env, create_walking_env +) class AdvancedRLTests: """Advanced RL functionality tests""" diff --git a/test_rl_functionality.py b/test_rl_functionality.py index f8d7054..a5ff4ff 100644 --- a/test_rl_functionality.py +++ b/test_rl_functionality.py @@ -4,6 +4,7 @@ Tests all aspects of the MuJoCo MCP RL integration """ +import importlib.util import sys import time import numpy as np @@ -11,22 +12,22 @@ from pathlib import Path from typing import Dict, Any +import pytest + # Add src to path for imports sys.path.insert(0, str(Path(__file__).parent / "src")) -try: - from mujoco_mcp.rl_integration import ( - RLConfig, MuJoCoRLEnvironment, RLTrainer, - ReachingTaskReward, BalancingTaskReward, WalkingTaskReward, - create_reaching_env, create_balancing_env, create_walking_env, - example_training - ) - from mujoco_mcp.viewer_client import MuJoCoViewerClient - from mujoco_mcp.simulation import MuJoCoSimulation -except ImportError as e: - print(f"❌ Import Error: {e}") - print("Make sure MuJoCo MCP is properly installed") - sys.exit(1) +if importlib.util.find_spec("gymnasium") is None: + pytest.skip("gymnasium is required for RL integration tests", allow_module_level=True) + +from mujoco_mcp.rl_integration import ( + RLConfig, MuJoCoRLEnvironment, RLTrainer, + ReachingTaskReward, BalancingTaskReward, WalkingTaskReward, + create_reaching_env, create_balancing_env, create_walking_env, + example_training +) +from mujoco_mcp.viewer_client import MuJoCoViewerClient +from mujoco_mcp.simulation import MuJoCoSimulation # Configure logging logging.basicConfig(level=logging.INFO) diff --git a/test_rl_integration.py b/test_rl_integration.py index 7bc05b6..ae23ad3 100644 --- a/test_rl_integration.py +++ b/test_rl_integration.py @@ -4,6 +4,7 @@ Tests RL functionality with actual MuJoCo physics simulation """ +import importlib.util import sys import time import subprocess @@ -15,19 +16,20 @@ import threading import logging +import pytest + # Add src to path for imports sys.path.insert(0, str(Path(__file__).parent / "src")) -try: - from mujoco_mcp.rl_integration import ( - RLConfig, MuJoCoRLEnvironment, RLTrainer, - create_reaching_env, create_balancing_env, create_walking_env - ) - from mujoco_mcp.viewer_server import MuJoCoViewerServer - from mujoco_mcp.viewer_client import MuJoCoViewerClient -except ImportError as e: - print(f"❌ Import Error: {e}") - sys.exit(1) +if importlib.util.find_spec("gymnasium") is None: + pytest.skip("gymnasium is required for RL integration tests", allow_module_level=True) + +from mujoco_mcp.rl_integration import ( + RLConfig, MuJoCoRLEnvironment, RLTrainer, + create_reaching_env, create_balancing_env, create_walking_env +) +from mujoco_mcp.viewer_server import MuJoCoViewerServer +from mujoco_mcp.viewer_client import MuJoCoViewerClient class RLIntegrationTest: """Test RL integration with MuJoCo viewer""" diff --git a/test_rl_simple.py b/test_rl_simple.py index 69c9f8d..62ed9c4 100644 --- a/test_rl_simple.py +++ b/test_rl_simple.py @@ -3,23 +3,25 @@ Simplified RL Test - Tests core RL functionality without MuJoCo viewer dependency """ +import importlib.util import sys import time import numpy as np from pathlib import Path +import pytest + # Add src to path for imports sys.path.insert(0, str(Path(__file__).parent / "src")) -try: - from mujoco_mcp.rl_integration import ( - RLConfig, MuJoCoRLEnvironment, RLTrainer, - create_reaching_env, create_balancing_env, create_walking_env, - example_training - ) -except ImportError as e: - print(f"❌ Import Error: {e}") - sys.exit(1) +if importlib.util.find_spec("gymnasium") is None: + pytest.skip("gymnasium is required for RL integration tests", allow_module_level=True) + +from mujoco_mcp.rl_integration import ( + RLConfig, MuJoCoRLEnvironment, RLTrainer, + create_reaching_env, create_balancing_env, create_walking_env, + example_training +) def test_rl_core_functionality(): """Test core RL functionality without MuJoCo viewer"""