mirror of
https://github.com/hanzoai/python-sdk.git
synced 2026-10-23 20:23:00 +00:00
fix: Fix hanzo-mcp test timeout issues
- Added proper mocking to LSP tool tests to prevent subprocess hangs - Mocked asyncio.create_subprocess_exec calls in all LSP tests - Fixed version assertion in test_hanzo_mcp_local (0.7.7 not 0.6.13) - Tests now complete in ~18 seconds instead of timing out at 5 minutes
This commit is contained in:
@@ -18,7 +18,7 @@ from hanzo_mcp.server import create_server
|
||||
def test_basic_import():
|
||||
"""Test that we can import hanzo-mcp."""
|
||||
print(f"✓ Successfully imported hanzo-mcp version {__version__}")
|
||||
assert __version__ == "0.6.13"
|
||||
assert __version__ == "0.7.7"
|
||||
|
||||
|
||||
def test_server_creation():
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import asyncio
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
from unittest.mock import AsyncMock, MagicMock, patch
|
||||
|
||||
import pytest
|
||||
from hanzo_mcp.tools.lsp import create_lsp_tool
|
||||
@@ -10,7 +11,7 @@ from hanzo_mcp.tools.lsp import create_lsp_tool
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_lsp_tool_status():
|
||||
"""Test LSP tool status check."""
|
||||
"""Test LSP tool status check with mocking."""
|
||||
lsp_tool = create_lsp_tool()
|
||||
|
||||
# Create a test Go file
|
||||
@@ -32,16 +33,24 @@ func greet(name string) string {
|
||||
go_file = f.name
|
||||
|
||||
try:
|
||||
# Check status for Go
|
||||
result = await lsp_tool.run(action="status", file=go_file)
|
||||
# Mock the subprocess calls to prevent hanging
|
||||
with patch("asyncio.create_subprocess_exec") as mock_subprocess:
|
||||
# Mock successful check for gopls
|
||||
mock_process = AsyncMock()
|
||||
mock_process.returncode = 0
|
||||
mock_process.communicate = AsyncMock(return_value=(b"", b""))
|
||||
mock_subprocess.return_value = mock_process
|
||||
|
||||
assert result.data is not None
|
||||
assert "language" in result.data
|
||||
assert result.data["language"] == "go"
|
||||
assert "lsp_server" in result.data
|
||||
assert result.data["lsp_server"] == "gopls"
|
||||
assert "capabilities" in result.data
|
||||
assert "definition" in result.data["capabilities"]
|
||||
# Check status for Go
|
||||
result = await lsp_tool.run(action="status", file=go_file)
|
||||
|
||||
assert result.data is not None
|
||||
assert "language" in result.data
|
||||
assert result.data["language"] == "go"
|
||||
assert "lsp_server" in result.data
|
||||
assert result.data["lsp_server"] == "gopls"
|
||||
assert "capabilities" in result.data
|
||||
assert "definition" in result.data["capabilities"]
|
||||
|
||||
finally:
|
||||
Path(go_file).unlink()
|
||||
@@ -76,7 +85,7 @@ async def test_lsp_tool_invalid_action():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_lsp_tool_definition_placeholder():
|
||||
"""Test LSP tool definition action (placeholder)."""
|
||||
"""Test LSP tool definition action (placeholder) with mocking."""
|
||||
lsp_tool = create_lsp_tool()
|
||||
|
||||
with tempfile.NamedTemporaryFile(suffix=".py", mode="w", delete=False) as f:
|
||||
@@ -90,19 +99,27 @@ result = hello()
|
||||
py_file = f.name
|
||||
|
||||
try:
|
||||
# Test definition lookup
|
||||
result = await lsp_tool.run(
|
||||
action="definition",
|
||||
file=py_file,
|
||||
line=4,
|
||||
character=9, # Position of 'hello' in 'hello()'
|
||||
)
|
||||
# Mock the subprocess calls
|
||||
with patch("asyncio.create_subprocess_exec") as mock_subprocess:
|
||||
# Mock successful check for pylsp
|
||||
mock_process = AsyncMock()
|
||||
mock_process.returncode = 0
|
||||
mock_process.communicate = AsyncMock(return_value=(b"", b""))
|
||||
mock_subprocess.return_value = mock_process
|
||||
|
||||
assert result.data is not None
|
||||
assert "action" in result.data
|
||||
assert result.data["action"] == "definition"
|
||||
assert "note" in result.data
|
||||
assert "fallback" in result.data
|
||||
# Test definition lookup
|
||||
result = await lsp_tool.run(
|
||||
action="definition",
|
||||
file=py_file,
|
||||
line=4,
|
||||
character=9, # Position of 'hello' in 'hello()'
|
||||
)
|
||||
|
||||
assert result.data is not None
|
||||
assert "action" in result.data
|
||||
assert result.data["action"] == "definition"
|
||||
assert "note" in result.data
|
||||
assert "fallback" in result.data
|
||||
|
||||
finally:
|
||||
Path(py_file).unlink()
|
||||
@@ -110,51 +127,75 @@ result = hello()
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_lsp_tool_python_status():
|
||||
"""Test LSP status for Python files."""
|
||||
"""Test LSP status for Python files with mocking."""
|
||||
lsp_tool = create_lsp_tool()
|
||||
|
||||
# Check Python LSP status
|
||||
result = await lsp_tool.run(action="status", file="test.py")
|
||||
# Mock the subprocess calls
|
||||
with patch("asyncio.create_subprocess_exec") as mock_subprocess:
|
||||
# Mock successful check for pylsp
|
||||
mock_process = AsyncMock()
|
||||
mock_process.returncode = 0
|
||||
mock_process.communicate = AsyncMock(return_value=(b"", b""))
|
||||
mock_subprocess.return_value = mock_process
|
||||
|
||||
assert result.data is not None
|
||||
assert result.data["language"] == "python"
|
||||
assert result.data["lsp_server"] == "pylsp"
|
||||
assert "definition" in result.data["capabilities"]
|
||||
assert "hover" in result.data["capabilities"]
|
||||
# Check Python LSP status
|
||||
result = await lsp_tool.run(action="status", file="test.py")
|
||||
|
||||
assert result.data is not None
|
||||
assert result.data["language"] == "python"
|
||||
assert result.data["lsp_server"] == "pylsp"
|
||||
assert "definition" in result.data["capabilities"]
|
||||
assert "hover" in result.data["capabilities"]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_lsp_tool_typescript_status():
|
||||
"""Test LSP status for TypeScript files."""
|
||||
"""Test LSP status for TypeScript files with mocking."""
|
||||
lsp_tool = create_lsp_tool()
|
||||
|
||||
# Check TypeScript LSP status
|
||||
result = await lsp_tool.run(action="status", file="app.ts")
|
||||
# Mock the subprocess calls
|
||||
with patch("asyncio.create_subprocess_exec") as mock_subprocess:
|
||||
# Mock successful check for typescript-language-server
|
||||
mock_process = AsyncMock()
|
||||
mock_process.returncode = 0
|
||||
mock_process.communicate = AsyncMock(return_value=(b"", b""))
|
||||
mock_subprocess.return_value = mock_process
|
||||
|
||||
assert result.data is not None
|
||||
assert result.data["language"] == "typescript"
|
||||
assert result.data["lsp_server"] == "typescript-language-server"
|
||||
assert "completion" in result.data["capabilities"]
|
||||
# Check TypeScript LSP status
|
||||
result = await lsp_tool.run(action="status", file="app.ts")
|
||||
|
||||
assert result.data is not None
|
||||
assert result.data["language"] == "typescript"
|
||||
assert result.data["lsp_server"] == "typescript-language-server"
|
||||
assert "completion" in result.data["capabilities"]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_lsp_tool_rename_placeholder():
|
||||
"""Test LSP rename action (placeholder)."""
|
||||
"""Test LSP rename action (placeholder) with mocking."""
|
||||
lsp_tool = create_lsp_tool()
|
||||
|
||||
# Test rename
|
||||
result = await lsp_tool.run(
|
||||
action="rename",
|
||||
file="test.go",
|
||||
line=10,
|
||||
character=5,
|
||||
new_name="newFunctionName",
|
||||
)
|
||||
# Mock the subprocess calls
|
||||
with patch("asyncio.create_subprocess_exec") as mock_subprocess:
|
||||
# Mock successful check
|
||||
mock_process = AsyncMock()
|
||||
mock_process.returncode = 0
|
||||
mock_process.communicate = AsyncMock(return_value=(b"", b""))
|
||||
mock_subprocess.return_value = mock_process
|
||||
|
||||
assert result.data is not None
|
||||
assert result.data["action"] == "rename"
|
||||
assert result.data["new_name"] == "newFunctionName"
|
||||
assert "fallback" in result.data
|
||||
# Test rename
|
||||
result = await lsp_tool.run(
|
||||
action="rename",
|
||||
file="test.go",
|
||||
line=10,
|
||||
character=5,
|
||||
new_name="newFunctionName",
|
||||
)
|
||||
|
||||
assert result.data is not None
|
||||
assert result.data["action"] == "rename"
|
||||
assert result.data["new_name"] == "newFunctionName"
|
||||
assert "fallback" in result.data
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
@@ -162,4 +203,4 @@ if __name__ == "__main__":
|
||||
asyncio.run(test_lsp_tool_status())
|
||||
asyncio.run(test_lsp_tool_unsupported_file())
|
||||
asyncio.run(test_lsp_tool_invalid_action())
|
||||
print("LSP tool tests passed!")
|
||||
print("LSP tool tests passed!")
|
||||
Reference in New Issue
Block a user