Skip to main content
Glama
test_debugger.py6.74 kB
""" Unit tests for debugger controller. Tests breakpoint functionality and variable capture. """ import tempfile from pathlib import Path from mcp_debug_tool.debugger import DebugController class TestDebugController: """Tests for DebugController breakpoint functionality.""" def test_run_to_single_breakpoint(self): """Test that debugger stops at a single breakpoint and captures locals.""" # Create a temporary test script with tempfile.NamedTemporaryFile(mode="w", suffix=".py", delete=False) as f: f.write(""" def test_function(): x = 42 y = "hello" z = [1, 2, 3] return x + len(z) # Line 6 - breakpoint here test_function() """) script_path = Path(f.name) try: debugger = DebugController() response = debugger.run_to_breakpoint(script_path, str(script_path), 6) # Verify breakpoint was hit assert response.hit is True assert response.completed is False assert response.error is None # Verify frame info assert response.frameInfo is not None assert response.frameInfo.line == 6 # Verify locals were captured assert response.locals is not None assert "x" in response.locals assert response.locals["x"]["type"] == "int" assert "42" in response.locals["x"]["repr"] assert "y" in response.locals assert response.locals["y"]["type"] == "str" assert "hello" in response.locals["y"]["repr"] assert "z" in response.locals assert response.locals["z"]["type"] == "list" finally: script_path.unlink() def test_breakpoint_not_reached(self): """Test when execution completes before breakpoint.""" # Create a script that finishes before the breakpoint line with tempfile.NamedTemporaryFile(mode="w", suffix=".py", delete=False) as f: f.write(""" x = 1 y = 2 # Line 4 is empty, execution ends before we reach line 10 """) script_path = Path(f.name) try: debugger = DebugController() response = debugger.run_to_breakpoint(script_path, str(script_path), 10) # Verify breakpoint was not hit assert response.hit is False assert response.completed is True assert response.locals is None finally: script_path.unlink() def test_captures_various_types(self): """Test that debugger captures various Python types correctly.""" with tempfile.NamedTemporaryFile(mode="w", suffix=".py", delete=False) as f: f.write(""" integer_var = 42 float_var = 3.14 string_var = "test" list_var = [1, 2, 3] dict_var = {"a": 1, "b": 2} tuple_var = (1, 2) set_var = {1, 2, 3} bool_var = True breakpoint_here = True # Line 10 """) script_path = Path(f.name) try: debugger = DebugController() response = debugger.run_to_breakpoint(script_path, str(script_path), 10) assert response.hit is True assert response.locals is not None # Check various types are captured assert "integer_var" in response.locals assert response.locals["integer_var"]["type"] == "int" assert "float_var" in response.locals assert response.locals["float_var"]["type"] == "float" assert "string_var" in response.locals assert response.locals["string_var"]["type"] == "str" assert "list_var" in response.locals assert response.locals["list_var"]["type"] == "list" assert "dict_var" in response.locals assert response.locals["dict_var"]["type"] == "dict" assert "bool_var" in response.locals assert response.locals["bool_var"]["type"] == "bool" # Note: None variables are not captured at module level # since they might not be in scope yet finally: script_path.unlink() def test_truncation_flag_for_large_collections(self): """Test that large collections are marked as truncated.""" with tempfile.NamedTemporaryFile(mode="w", suffix=".py", delete=False) as f: f.write(""" large_list = list(range(1000)) # Much larger than MAX_CONTAINER_ITEMS breakpoint_here = True # Line 3 """) script_path = Path(f.name) try: debugger = DebugController() response = debugger.run_to_breakpoint(script_path, str(script_path), 3) assert response.hit is True assert response.locals is not None assert "large_list" in response.locals # Should be marked as truncated due to size var_info = response.locals["large_list"] assert var_info["length"] == 1000 assert var_info["isTruncated"] is True finally: script_path.unlink() def test_exception_during_execution(self): """Test handling of exceptions before breakpoint.""" with tempfile.NamedTemporaryFile(mode="w", suffix=".py", delete=False) as f: f.write(""" x = 1 y = 0 z = x / y # This will raise ZeroDivisionError breakpoint_here = True # Line 5 - never reached """) script_path = Path(f.name) try: debugger = DebugController() response = debugger.run_to_breakpoint(script_path, str(script_path), 5) # Breakpoint should not be hit due to exception assert response.hit is False assert response.error is not None assert response.error.type == "ZeroDivisionError" finally: script_path.unlink() def test_skips_private_variables(self): """Test that private variables (starting with __) are skipped.""" with tempfile.NamedTemporaryFile(mode="w", suffix=".py", delete=False) as f: f.write(""" public_var = 42 _private_var = "should appear" __dunder_var__ = "should not appear" breakpoint_here = True # Line 5 """) script_path = Path(f.name) try: debugger = DebugController() response = debugger.run_to_breakpoint(script_path, str(script_path), 5) assert response.hit is True assert response.locals is not None # Public and single underscore should be captured assert "public_var" in response.locals assert "_private_var" in response.locals # Dunder variables should be skipped assert "__dunder_var__" not in response.locals finally: script_path.unlink()

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/Kaina3/Debug-MCP'

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