"""Unit tests for complexity analysis module.""" from codesnap.core.complexity import ( ComplexityMetrics, analyze_file_complexity, calculate_cyclomatic_complexity, calculate_nesting_depth, count_lines, get_complexity_summary, rate_complexity, ) from codesnap.core.parser import FunctionInfo class TestCalculateCyclomaticComplexity: """Tests for cyclomatic complexity calculation.""" def test_empty_content(self): complexity, decisions = calculate_cyclomatic_complexity("") assert complexity == 1 assert decisions == 0 def test_simple_function(self): content = "def test():\n pass" complexity, decisions = calculate_cyclomatic_complexity(content) assert complexity == 1 def test_if_statement(self): content = "if x > 0:\n pass" complexity, decisions = calculate_cyclomatic_complexity(content) assert complexity >= 1 def test_multiple_if_statements(self): content = """ if x > 0: pass elif x < 0: pass else: pass """ complexity, decisions = calculate_cyclomatic_complexity(content) assert complexity >= 3 def test_for_loop(self): content = "for i in range(10):\n pass" complexity, decisions = calculate_cyclomatic_complexity(content) assert complexity >= 1 def test_while_loop(self): content = "while True:\n pass" complexity, decisions = calculate_cyclomatic_complexity(content) assert complexity >= 1 def test_try_except(self): content = """ try: pass except Exception: pass """ complexity, decisions = calculate_cyclomatic_complexity(content) assert complexity >= 1 def test_and_or_operators(self): content = "if x > 0 and y > 0:\n pass" complexity, decisions = calculate_cyclomatic_complexity(content) assert complexity >= 2 def test_ternary_operator(self): content = "x = 1 if cond else 2" complexity, decisions = calculate_cyclomatic_complexity(content) assert complexity >= 1 class TestCalculateNestingDepth: """Tests for nesting depth calculation.""" def test_flat_code(self): depth = calculate_nesting_depth("x = 1\ny = 2") assert depth >= 0 def test_single_brace_level(self): depth = calculate_nesting_depth("if x: { y = 1 }") assert depth >= 0 def test_nested_braces(self): content = """ if x: if y: if z: pass """ depth = calculate_nesting_depth(content) assert depth >= 0 # Depends on brace detection def test_mixed_brackets(self): content = """ def test(): data = [ [1, 2], {a: b} ] """ depth = calculate_nesting_depth(content) assert depth >= 1 def test_balanced_brackets(self): content = "[](){}" depth = calculate_nesting_depth(content) assert depth >= 1 def test_unbalanced_close(self): content = "x = 1]" depth = calculate_nesting_depth(content) assert depth >= 0 class TestCountLines: """Tests for line counting.""" def test_empty_content(self): total, comments = count_lines("") assert total >= 0 assert comments >= 0 def test_single_line(self): total, comments = count_lines("x = 1") assert total >= 1 assert comments >= 0 def test_python_comments(self): content = "# This is a comment\nx = 1\n# Another comment" total, comments = count_lines(content) assert total >= 3 assert comments >= 2 def test_python_docstring(self): content = '"""This is a docstring"""' total, comments = count_lines(content) assert total >= 1 def test_multiline_python_comment(self): content = """ ''' Multiline Comment ''' x = 1 """ total, comments = count_lines(content) assert total >= 5 def test_cpp_comments(self): content = "// Single line comment\nx = 1;" total, comments = count_lines(content) assert total >= 2 assert comments >= 1 def test_c_multiline_comment(self): content = "/* Multi\n Line */\nx = 1;" total, comments = count_lines(content) assert total >= 3 assert comments >= 1 class TestRateComplexity: """Tests for complexity rating.""" def test_low_complexity(self): assert rate_complexity(1, 1) == "low" assert rate_complexity(5, 2) == "low" assert rate_complexity(9, 3) == "low" def test_medium_complexity(self): assert rate_complexity(10, 3) == "medium" assert rate_complexity(15, 4) == "medium" assert rate_complexity(19, 5) == "medium" def test_high_complexity(self): assert rate_complexity(20, 3) == "high" assert rate_complexity(25, 6) == "high" assert rate_complexity(50, 2) == "high" def test_high_nesting(self): result = rate_complexity(5, 6) assert result in ["low", "medium", "high"] class TestAnalyzeFileComplexity: """Tests for file complexity analysis.""" def test_empty_file(self): metrics, func_complexities = analyze_file_complexity("", [], "python") assert metrics.cyclomatic_complexity >= 1 assert len(func_complexities) == 0 def test_simple_file(self): content = "x = 1\ny = 2" metrics, func_complexities = analyze_file_complexity(content, [], "python") assert metrics.complexity_rating in ["low", "medium", "high"] def test_complex_file(self): content = """ def test(): if x > 0: if y > 0: if z > 0: pass """ func = FunctionInfo( name="test", node_type="function", start_line=1, end_line=6, parameters=[], ) metrics, func_complexities = analyze_file_complexity(content, [func], "python") assert metrics.complexity_rating in ["low", "medium", "high"] assert len(func_complexities) >= 0 def test_suggestions_generated(self): content = """ def test(): pass """ * 25 metrics, func_complexities = analyze_file_complexity(content, [], "python") assert isinstance(metrics.suggestions, list) class TestGetComplexitySummary: """Tests for complexity summary generation.""" def test_empty_list(self): summary = get_complexity_summary([]) assert summary["total_files"] == 0 assert summary["avg_complexity"] == 0 def test_single_file(self): metrics = ComplexityMetrics( cyclomatic_complexity=10, nesting_depth=2, lines_of_code=50, ) summary = get_complexity_summary([metrics]) assert summary["total_files"] == 1 assert summary["avg_complexity"] == 10 def test_multiple_files(self): metrics_list = [ ComplexityMetrics(cyclomatic_complexity=5), ComplexityMetrics(cyclomatic_complexity=15), ComplexityMetrics(cyclomatic_complexity=10), ] summary = get_complexity_summary(metrics_list) assert summary["total_files"] == 3 assert summary["avg_complexity"] == 10 def test_rating_distribution(self): metrics_list = [ ComplexityMetrics(cyclomatic_complexity=5), ComplexityMetrics(cyclomatic_complexity=15), ComplexityMetrics(cyclomatic_complexity=25), ] summary = get_complexity_summary(metrics_list) assert summary["rating_distribution"]["low"] >= 0 assert summary["rating_distribution"]["medium"] >= 0 assert summary["rating_distribution"]["high"] >= 0 assert summary["rating_distribution"]["low"] + summary["rating_distribution"]["medium"] + summary["rating_distribution"]["high"] == 3