from pathlib import Path from src.analyzers.complexity import ComplexityCalculator from src.analyzers.dependencies import DependencyAnalyzer from src.graph.builder import GraphBuilder, GraphType, GraphNode, NodeType from src.parsers.base import Entity, EntityType class TestComplexityCalculator: def setup_method(self): self.calculator = ComplexityCalculator() def test_simple_function_complexity(self): entity = Entity( name="simple_func", entity_type=EntityType.FUNCTION, file_path=Path("/test.py"), start_line=1, end_line=5, code="def simple_func():\n pass", ) result = self.calculator.calculate_for_entity(entity) assert result["complexity_score"] == 1 assert result["name"] == "simple_func" def test_function_with_if_statement(self): entity = Entity( name="func_with_if", entity_type=EntityType.FUNCTION, file_path=Path("/test.py"), start_line=1, end_line=10, code="def func_with_if(x):\n if x > 0:\n return True\n return False", ) result = self.calculator.calculate_for_entity(entity) assert result["complexity_score"] == 2 assert result["decision_points"] == 1 def test_function_with_multiple_decision_points(self): entity = Entity( name="complex_func", entity_type=EntityType.FUNCTION, file_path=Path("/test.py"), start_line=1, end_line=20, code="""def complex_func(x): if x > 0: if x > 10: return "big" else: return "small" elif x < 0: return "negative" else: return "zero" """, ) result = self.calculator.calculate_for_entity(entity) assert result["complexity_score"] >= 4 def test_function_with_loop(self): entity = Entity( name="func_with_loop", entity_type=EntityType.FUNCTION, file_path=Path("/test.py"), start_line=1, end_line=10, code="def func_with_loop(items):\n for item in items:\n print(item)", ) result = self.calculator.calculate_for_entity(entity) assert result["complexity_score"] == 2 def test_method_complexity(self): entity = Entity( name="method", entity_type=EntityType.METHOD, file_path=Path("/test.py"), start_line=1, end_line=8, code="def process(self, data):\n if data:\n for item in data:\n if item.valid:\n pass", ) result = self.calculator.calculate_for_entity(entity) assert result["entity_type"] == "method" def test_complexity_threshold(self): assert self.calculator.complexity_threshold == 10 def test_set_complexity_threshold(self): self.calculator.set_complexity_threshold(15) assert self.calculator.complexity_threshold == 15 def test_is_complex_flag(self): entity = Entity( name="simple", entity_type=EntityType.FUNCTION, file_path=Path("/test.py"), start_line=1, end_line=5, code="def simple():\n pass", ) result = self.calculator.calculate_for_entity(entity) assert result["is_complex"] is False def test_high_complexity_flag(self): entity = Entity( name="complex", entity_type=EntityType.FUNCTION, file_path=Path("/test.py"), start_line=1, end_line=30, code="def complex():\n if True:\n if True:\n if True:\n if True:\n if True:\n if True:\n if True:\n if True:\n if True:\n if True:\n if True:\n pass", ) result = self.calculator.calculate_for_entity(entity) assert result["is_complex"] is True def test_calculate_project_complexity(self): entities = [ Entity( name="func1", entity_type=EntityType.FUNCTION, file_path=Path("/test.py"), start_line=1, end_line=5, code="def func1():\n pass", ), Entity( name="func2", entity_type=EntityType.FUNCTION, file_path=Path("/test.py"), start_line=10, end_line=20, code="def func2():\n if True:\n pass", ), ] report = self.calculator.calculate_project_complexity(entities) assert report["total_functions"] == 2 assert report["total_cyclomatic_complexity"] >= 2 assert "complexity_distribution" in report def test_complexity_distribution(self): entities = [ Entity( name=f"func{i}", entity_type=EntityType.FUNCTION, file_path=Path("/test.py"), start_line=1, end_line=5, code="def func():\n pass", ) for i in range(10) ] report = self.calculator.calculate_project_complexity(entities) assert report["complexity_distribution"]["low"] == 10 class TestDependencyAnalyzer: def setup_method(self): self.builder = GraphBuilder(GraphType.DIRECTED) self.analyzer = DependencyAnalyzer(self.builder) def test_analyze_empty_graph(self): report = self.analyzer.analyze() assert report.total_files == 0 assert report.total_functions == 0 assert report.total_classes == 0 def test_count_entities(self): file_node = GraphNode(node_id="file1", node_type=NodeType.FILE, name="test.py") func_node = GraphNode(node_id="func1", node_type=NodeType.FUNCTION, name="test_func") class_node = GraphNode(node_id="class1", node_type=NodeType.CLASS, name="TestClass") self.builder.add_node(file_node) self.builder.add_node(func_node) self.builder.add_node(class_node) report = self.analyzer.analyze() assert report.total_files == 1 assert report.total_functions == 1 assert report.total_classes == 1 def test_get_architecture_layers(self): file_node = GraphNode( node_id="controller", node_type=NodeType.FILE, name="controller.py", file_path=Path("/src/ui/controller.py"), ) self.builder.add_node(file_node) layers = self.analyzer.get_architecture_layers() assert "presentation" in layers or "other" in layers def test_get_file_dependencies(self): file_node = GraphNode( node_id="file_test.py", node_type=NodeType.FILE, name="test.py", file_path=Path("/test.py"), ) self.builder.add_node(file_node) deps = self.analyzer.get_file_dependencies(Path("/test.py")) assert isinstance(deps, list) class TestComplexityReport: def test_report_creation(self): from src.analyzers.complexity import ComplexityReport report = ComplexityReport(file_path=Path("/test.py")) assert report.file_path == Path("/test.py") assert report.functions == [] assert report.classes == [] assert report.total_cyclomatic_complexity == 0 def test_average_complexity_calculation(self): from src.analyzers.complexity import ComplexityReport report = ComplexityReport(file_path=Path("/test.py")) report.functions = [ {"complexity_score": 5}, {"complexity_score": 10}, {"complexity_score": 15}, ] expected_avg = (5 + 10 + 15) / 3 actual_avg = sum(f["complexity_score"] for f in report.functions) / len( report.functions ) assert actual_avg == expected_avg