Coverage for tests / test_call_graph / test_parser.py: 100%

53 statements  

« prev     ^ index     » next       coverage.py v7.13.3, created at 2026-02-08 15:04 -0800

1"""Tests for call graph parser.""" 

2 

3from __future__ import annotations 

4 

5from pathlib import Path 

6 

7from call_graph.parsers.python import PythonCallParser 

8from parsers.python import parse 

9 

10 

11def test_extract_function_definitions(): 

12 code = """ 

13def foo(x, y): 

14 return x + y 

15 

16class Bar: 

17 def method_a(self): 

18 pass 

19  

20 def method_b(self): 

21 pass 

22 

23def baz(): 

24 pass 

25""" 

26 parser = PythonCallParser() 

27 root = parse(code) 

28 defs = parser.extract_function_definitions(root, code, "/tmp/test.py") 

29 

30 assert len(defs) == 4 

31 def_names = [d.name for d in defs] 

32 assert "foo" in def_names 

33 assert "method_a" in def_names 

34 assert "method_b" in def_names 

35 assert "baz" in def_names 

36 

37 func_def = next(d for d in defs if d.name == "foo") 

38 assert func_def.def_type == "function" 

39 assert len(func_def.params) == 2 

40 

41 method_def = next(d for d in defs if d.name == "method_a") 

42 assert method_def.def_type == "method" 

43 assert method_def.class_name == "Bar" 

44 

45 

46def test_extract_simple_calls(): 

47 code = """ 

48def foo(): 

49 bar() 

50  

51def bar(): 

52 baz() 

53 

54def baz(): 

55 pass 

56""" 

57 parser = PythonCallParser() 

58 root = parse(code) 

59 defs = parser.extract_function_definitions(root, code, "/tmp/test.py") 

60 calls = parser.extract_calls(root, code, "/tmp/test.py", defs) 

61 

62 assert len(calls) == 2 

63 

64 call_names = [c.callee_function for c in calls] 

65 assert "bar" in call_names 

66 assert "baz" in call_names 

67 

68 foo_to_bar = next(c for c in calls if c.caller_function == "foo") 

69 assert foo_to_bar.callee_function == "bar" 

70 assert foo_to_bar.call_type == "local" 

71 

72 

73def test_extract_method_calls(): 

74 code = """ 

75class MyClass: 

76 def foo(self): 

77 self.bar() 

78  

79 def bar(self): 

80 pass 

81""" 

82 parser = PythonCallParser() 

83 root = parse(code) 

84 defs = parser.extract_function_definitions(root, code, "/tmp/test.py") 

85 calls = parser.extract_calls(root, code, "/tmp/test.py", defs) 

86 

87 assert len(calls) == 1 

88 assert calls[0].callee_function == "bar" 

89 assert calls[0].call_type == "method" 

90 assert calls[0].receiver_object == "self" 

91 

92 

93def test_extract_external_calls(): 

94 code = """ 

95def foo(): 

96 print("hello") 

97 len([1, 2, 3]) 

98""" 

99 parser = PythonCallParser() 

100 root = parse(code) 

101 defs = parser.extract_function_definitions(root, code, "/tmp/test.py") 

102 calls = parser.extract_calls(root, code, "/tmp/test.py", defs) 

103 

104 assert len(calls) == 2 

105 external_calls = [c for c in calls if c.call_type == "external"] 

106 assert len(external_calls) == 2