Skip to main content
Glama
test_robot_model_tools.py7.14 kB
"""Unit tests for robot_model_tools.""" import pytest from unittest.mock import AsyncMock, MagicMock, patch from pathlib import Path from robotics_mcp.tools.robot_model_tools import RobotModelTools, ROBOT_MODEL_FORMATS from robotics_mcp.utils.state_manager import RobotStateManager @pytest.fixture def mock_mcp(): """Create mock MCP server.""" mcp = MagicMock() mcp.tool = MagicMock(return_value=lambda f: f) return mcp @pytest.fixture def state_manager(): """Create robot state manager.""" return RobotStateManager() @pytest.fixture def mock_mounted_servers(): """Create mock mounted servers.""" return { "blender": MagicMock(), "gimp": MagicMock(), } @pytest.fixture def robot_model_tools(mock_mcp, state_manager, mock_mounted_servers): """Create robot model tools instance.""" tool = RobotModelTools(mock_mcp, state_manager, mock_mounted_servers) tool.register() return tool @pytest.mark.asyncio async def test_robot_model_create_scout(robot_model_tools, tmp_path): """Test creating Scout model.""" tool_func = robot_model_tools.mcp.tool.call_args[0][0] output_path = str(tmp_path / "scout_model.fbx") with patch("robotics_mcp.tools.robot_model_tools.get_blender_executor") as mock_executor: mock_exec = MagicMock() mock_executor.return_value = mock_exec mock_exec.execute_script = AsyncMock() with patch("robotics_mcp.tools.robot_model_tools.Client") as mock_client: mock_client_instance = AsyncMock() mock_client.return_value.__aenter__.return_value = mock_client_instance mock_client_instance.call_tool = AsyncMock(return_value={"success": True}) result = await tool_func( operation="create", robot_type="scout", output_path=output_path, format="fbx", ) assert result["success"] is True assert "output_path" in result["data"] @pytest.mark.asyncio async def test_robot_model_create_invalid_type(robot_model_tools): """Test creating model with invalid robot type.""" tool_func = robot_model_tools.mcp.tool.call_args[0][0] result = await tool_func( operation="create", robot_type="invalid_type", output_path="/tmp/test.fbx", ) assert result["success"] is False assert "not supported" in result["error"].lower() or "invalid" in result["error"].lower() @pytest.mark.asyncio async def test_robot_model_import(robot_model_tools, tmp_path): """Test importing model.""" model_path = tmp_path / "scout.fbx" model_path.touch() # Create empty file tool_func = robot_model_tools.mcp.tool.call_args[0][0] with patch("robotics_mcp.tools.robot_model_tools.Client") as mock_client: mock_client_instance = AsyncMock() mock_client.return_value.__aenter__.return_value = mock_client_instance mock_client_instance.call_tool = AsyncMock(return_value={"success": True, "imported_path": str(model_path)}) result = await tool_func( operation="import", robot_type="scout", model_path=str(model_path), platform="unity", ) assert result["success"] is True @pytest.mark.asyncio async def test_robot_model_import_missing_file(robot_model_tools): """Test importing non-existent model file.""" tool_func = robot_model_tools.mcp.tool.call_args[0][0] result = await tool_func( operation="import", robot_type="scout", model_path="/nonexistent/file.fbx", ) assert result["success"] is False assert "not found" in result["error"].lower() @pytest.mark.asyncio async def test_robot_model_export(robot_model_tools, state_manager, tmp_path): """Test exporting model.""" # Register a robot first state_manager.register_robot("vbot_scout_01", "scout", platform="unity") tool_func = robot_model_tools.mcp.tool.call_args[0][0] output_path = str(tmp_path / "exported.fbx") with patch("robotics_mcp.tools.robot_model_tools.Client") as mock_client: mock_client_instance = AsyncMock() mock_client.return_value.__aenter__.return_value = mock_client_instance mock_client_instance.call_tool = AsyncMock(return_value={"success": True, "exported_path": output_path}) result = await tool_func( operation="export", robot_id="vbot_scout_01", output_path=output_path, format="fbx", ) assert result["success"] is True @pytest.mark.asyncio async def test_robot_model_convert(robot_model_tools, tmp_path): """Test converting model format.""" source_path = tmp_path / "scout.fbx" source_path.touch() target_path = tmp_path / "scout.glb" tool_func = robot_model_tools.mcp.tool.call_args[0][0] with patch("robotics_mcp.tools.robot_model_tools.Client") as mock_client: mock_client_instance = AsyncMock() mock_client.return_value.__aenter__.return_value = mock_client_instance mock_client_instance.call_tool = AsyncMock(return_value={"success": True, "converted_path": str(target_path)}) result = await tool_func( operation="convert", source_path=str(source_path), source_format="fbx", target_format="glb", target_path=str(target_path), ) assert result["success"] is True @pytest.mark.asyncio async def test_robot_model_invalid_operation(robot_model_tools): """Test invalid operation.""" tool_func = robot_model_tools.mcp.tool.call_args[0][0] result = await tool_func( operation="invalid_op", ) assert result["success"] is False assert "unknown operation" in result["error"].lower() @pytest.mark.asyncio async def test_robot_model_all_formats(robot_model_tools, tmp_path): """Test all supported formats.""" tool_func = robot_model_tools.mcp.tool.call_args[0][0] with patch("robotics_mcp.tools.robot_model_tools.get_blender_executor") as mock_executor: mock_exec = MagicMock() mock_executor.return_value = mock_exec mock_exec.execute_script = AsyncMock() with patch("robotics_mcp.tools.robot_model_tools.Client") as mock_client: mock_client_instance = AsyncMock() mock_client.return_value.__aenter__.return_value = mock_client_instance mock_client_instance.call_tool = AsyncMock(return_value={"success": True}) for fmt in ROBOT_MODEL_FORMATS: output_path = tmp_path / f"test.{fmt}" result = await tool_func( operation="create", robot_type="scout", output_path=str(output_path), format=fmt, ) # Should handle format (may fail for some, but should not crash) assert result is not None

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/sandraschi/robotics-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server