test_run_to_breakpoint.py•8.78 kB
"""
Integration tests for run_to_breakpoint functionality.
Tests the full flow from session creation to breakpoint hit.
"""
import sys
import pytest
from mcp_debug_tool.schemas import BreakpointRequest, StartSessionRequest
from mcp_debug_tool.sessions import SessionManager
@pytest.fixture
def workspace_root(tmp_path):
"""Create a temporary workspace."""
return tmp_path
@pytest.fixture
def test_script(workspace_root):
"""Create a test script with breakpoint locations."""
script_path = workspace_root / "test_script.py"
script_path.write_text("""def calculate(a, b):
result = a + b
return result # Line 3 - breakpoint location 1
x = 10
y = 20
z = calculate(x, y)
print(f"Result: {z}") # Line 8 - breakpoint location 2
""")
return script_path
@pytest.fixture
def session_manager(workspace_root):
"""Create a session manager."""
return SessionManager(workspace_root)
class TestRunToBreakpoint:
"""Integration tests for run_to_breakpoint."""
def test_run_to_first_breakpoint_returns_locals(
self, session_manager, test_script
):
"""Test that running to first breakpoint returns expected locals."""
# Create session
create_request = StartSessionRequest(
pythonPath=sys.executable,
entry=test_script.relative_to(session_manager.workspace_root).as_posix()
)
create_response = session_manager.create_session(create_request)
session_id = create_response.sessionId
# Run to breakpoint
bp_request = BreakpointRequest(
file=test_script.relative_to(session_manager.workspace_root).as_posix(),
line=3,
)
response = session_manager.run_to_breakpoint(session_id, bp_request)
# Verify breakpoint was hit
assert response.hit is True, "Breakpoint should be hit"
assert response.completed is False, "Execution should not be completed"
assert response.error is None, "No error should occur"
# Verify frame info
assert response.frameInfo is not None
assert response.frameInfo.line == 3
# Verify locals contain function parameters
assert response.locals is not None
assert "a" in response.locals
assert "b" in response.locals
assert "result" in response.locals
# Verify values
assert "10" in response.locals["a"]["repr"]
assert "20" in response.locals["b"]["repr"]
assert "30" in response.locals["result"]["repr"]
# Clean up
session_manager.end_session(session_id)
def test_run_to_module_level_breakpoint(self, session_manager, test_script):
"""Test running to a module-level breakpoint."""
# Create session
create_request = StartSessionRequest(
pythonPath=sys.executable,
entry=test_script.relative_to(session_manager.workspace_root).as_posix()
)
create_response = session_manager.create_session(create_request)
session_id = create_response.sessionId
# Run to module-level breakpoint (line 8 is after z = calculate(...))
bp_request = BreakpointRequest(
file=test_script.relative_to(session_manager.workspace_root).as_posix(),
line=8,
)
response = session_manager.run_to_breakpoint(session_id, bp_request)
# Verify breakpoint was hit
assert response.hit is True
assert response.locals is not None
# Should see module-level variables - x, y defined but z not yet assigned
assert "x" in response.locals
assert "y" in response.locals
# Note: z might not be captured yet depending on exact line timing
# Clean up
session_manager.end_session(session_id)
def test_invalid_file_path(self, session_manager, workspace_root):
"""Test error handling for invalid file path."""
# Create session with non-existent script
with pytest.raises(FileNotFoundError):
create_request = StartSessionRequest(entry="nonexistent.py", pythonPath=sys.executable)
session_manager.create_session(create_request)
def test_invalid_line_number(self, session_manager, test_script):
"""Test error handling for invalid line number."""
# Create session
create_request = StartSessionRequest(
pythonPath=sys.executable,
entry=test_script.relative_to(session_manager.workspace_root).as_posix()
)
create_response = session_manager.create_session(create_request)
session_id = create_response.sessionId
# Try breakpoint on line beyond file length
with pytest.raises(ValueError, match="exceeds file length"):
bp_request = BreakpointRequest(
file=test_script.relative_to(
session_manager.workspace_root
).as_posix(),
line=1000,
)
session_manager.run_to_breakpoint(session_id, bp_request)
# Clean up
session_manager.end_session(session_id)
def test_breakpoint_with_command_line_args(self, session_manager, workspace_root):
"""Test breakpoint with command-line arguments."""
# Create script that uses sys.argv
script_path = workspace_root / "args_script.py"
script_path.write_text("""import sys
args = sys.argv[1:]
first_arg = args[0] if args else None # Line 3
print(f"Args: {args}")
""")
# Create session with args
create_request = StartSessionRequest(
pythonPath=sys.executable,
entry=script_path.relative_to(session_manager.workspace_root).as_posix(),
args=["arg1", "arg2"],
)
create_response = session_manager.create_session(create_request)
session_id = create_response.sessionId
# Run to breakpoint
bp_request = BreakpointRequest(
file=script_path.relative_to(session_manager.workspace_root).as_posix(),
line=3,
)
response = session_manager.run_to_breakpoint(session_id, bp_request)
# Verify breakpoint was hit
assert response.hit is True
assert response.locals is not None
# Clean up
session_manager.end_session(session_id)
def test_breakpoint_with_environment_variables(
self, session_manager, workspace_root
):
"""Test breakpoint with environment variables."""
# Create script that uses environment variable
script_path = workspace_root / "env_script.py"
script_path.write_text("""import os
debug_mode = os.getenv("DEBUG_MODE", "off")
print(f"Debug: {debug_mode}") # Line 3
""")
# Create session with env vars
create_request = StartSessionRequest(
pythonPath=sys.executable,
entry=script_path.relative_to(session_manager.workspace_root).as_posix(),
env={"DEBUG_MODE": "on"},
)
create_response = session_manager.create_session(create_request)
session_id = create_response.sessionId
# Run to breakpoint
bp_request = BreakpointRequest(
file=script_path.relative_to(session_manager.workspace_root).as_posix(),
line=3,
)
response = session_manager.run_to_breakpoint(session_id, bp_request)
# Verify breakpoint was hit
assert response.hit is True
assert response.locals is not None
# Note: debug_mode might not be in locals at line 3 (after assignment completes)
# Just verify the breakpoint worked
# Clean up
session_manager.end_session(session_id)
def test_session_state_after_breakpoint(self, session_manager, test_script):
"""Test that session state is updated after breakpoint."""
# Create session
create_request = StartSessionRequest(
pythonPath=sys.executable,
entry=test_script.relative_to(session_manager.workspace_root).as_posix()
)
create_response = session_manager.create_session(create_request)
session_id = create_response.sessionId
# Run to breakpoint
bp_request = BreakpointRequest(
file=test_script.relative_to(session_manager.workspace_root).as_posix(),
line=3,
)
session_manager.run_to_breakpoint(session_id, bp_request)
# Check session state
state = session_manager.get_state(session_id)
assert state.status == "paused"
assert state.lastBreakpoint is not None
assert state.lastBreakpoint.line == 3
assert state.lastBreakpoint.hitCount == 1
assert state.timings.lastRunMs is not None
# Clean up
session_manager.end_session(session_id)