Skip to main content
Glama
test_intelligent_refactoring.py11.1 kB
#!/usr/bin/env python3 """ Tests for Intelligent Refactoring Tools This module contains comprehensive tests for the Kotlin refactoring functionality including rename, extract, inline, and introduce parameter refactorings. """ import asyncio import tempfile from pathlib import Path from unittest.mock import Mock, patch import pytest from tools.intelligent_refactoring import ( IntelligentRefactoringTools, KotlinASTParser, UnifiedDiffGenerator, ) class TestKotlinASTParser: """Test cases for Kotlin AST parser.""" def setup_method(self): self.parser = KotlinASTParser() def test_parse_simple_class(self): """Test parsing a simple Kotlin class.""" kotlin_code = """ class User { val name: String = "" var age: Int = 0 fun getDisplayName(): String { return name } fun incrementAge() { age += 1 } } """.strip() with tempfile.NamedTemporaryFile(mode="w", suffix=".kt", delete=False) as f: f.write(kotlin_code) temp_file = f.name try: symbols = self.parser.parse_file(temp_file) assert "User" in symbols assert symbols["User"]["type"] == "class" assert "getDisplayName" in symbols assert symbols["getDisplayName"]["type"] == "function" assert "incrementAge" in symbols assert "name" in symbols assert symbols["name"]["type"] == "property" finally: Path(temp_file).unlink() def test_parse_function_with_parameters(self): """Test parsing function with parameters.""" kotlin_code = """ fun calculateTotal(price: Double, tax: Double = 0.0): Double { return price + (price * tax) } """.strip() with tempfile.NamedTemporaryFile(mode="w", suffix=".kt", delete=False) as f: f.write(kotlin_code) temp_file = f.name try: symbols = self.parser.parse_file(temp_file) assert "calculateTotal" in symbols func_info = symbols["calculateTotal"] assert func_info["type"] == "function" assert len(func_info["parameters"]) == 2 assert func_info["parameters"][0]["name"] == "price" assert func_info["parameters"][0]["type"] == "Double" assert func_info["return_type"] == "Double" finally: Path(temp_file).unlink() class TestUnifiedDiffGenerator: """Test cases for unified diff generation.""" def test_generate_diff_simple_change(self): """Test generating diff for simple change.""" original = 'fun hello() {\n println("Hello")\n}' modified = 'fun hello() {\n println("Hello World")\n}' diff = UnifiedDiffGenerator.generate_diff(original, modified, "Test.kt") assert "@@ -1,3 +1,3 @@" in diff assert '- println("Hello")' in diff assert '+ println("Hello World")' in diff def test_generate_diff_no_changes(self): """Test generating diff when no changes.""" content = 'fun hello() {\n println("Hello")\n}' diff = UnifiedDiffGenerator.generate_diff(content, content, "Test.kt") assert diff == "" class TestIntelligentRefactoringTools: """Test cases for intelligent refactoring tools.""" def setup_method(self): self.project_path = Path(tempfile.mkdtemp()) self.tools = IntelligentRefactoringTools(str(self.project_path)) def teardown_method(self): # Clean up temp directory import shutil shutil.rmtree(self.project_path, ignore_errors=True) @pytest.mark.asyncio async def test_rename_function_success(self): """Test successful function rename.""" kotlin_code = """ class Calculator { fun add(a: Int, b: Int): Int { return a + b } fun calculate() { val result = add(5, 3) println(result) } } """.strip() # Create test file test_file = self.project_path / "Calculator.kt" test_file.write_text(kotlin_code) # Mock ktlint to return modified content modified_kotlin_code = """ class Calculator { fun sum(a: Int, b: Int): Int { return a + b } fun calculate() { val result = sum(5, 3) println(result) } } """.strip() with patch.object(self.tools.ktlint, "format_file", return_value=modified_kotlin_code): # Mock gradle build to succeed with patch.object( self.tools.gradle_api, "build_project", return_value={"success": True} ): result = await self.tools.refactor_function( { "filePath": str(test_file), "functionName": "add", "refactorType": "rename", "newName": "sum", "preview": True, } ) assert result["success"] is True assert "diff" in result assert "sum" in result["diff"] assert result["preview"] is True @pytest.mark.asyncio async def test_rename_function_missing_new_name(self): """Test rename function with missing new name.""" result = await self.tools.refactor_function( {"filePath": "test.kt", "functionName": "testFunc", "refactorType": "rename"} ) assert result["success"] is False assert "newName is required" in result["error"] @pytest.mark.asyncio async def test_extract_function_success(self): """Test successful function extraction.""" kotlin_code = """ fun processData() { val data = listOf(1, 2, 3, 4, 5) val filtered = data.filter { it > 2 } val mapped = filtered.map { it * 2 } println(mapped) } """.strip() # Create test file test_file = self.project_path / "Processor.kt" test_file.write_text(kotlin_code) # Mock ktlint and gradle with patch.object(self.tools.ktlint, "format_file", return_value=kotlin_code): with patch.object( self.tools.gradle_api, "build_project", return_value={"success": True} ): result = await self.tools.refactor_function( { "filePath": str(test_file), "functionName": "processData", "refactorType": "extract", "newName": "transformData", "range": {"start": {"line": 2}, "end": {"line": 4}}, "preview": True, } ) assert result["success"] is True assert "diff" in result @pytest.mark.asyncio async def test_inline_function_success(self): """Test successful function inlining.""" kotlin_code = """ fun getMessage(): String { return "Hello World" } fun displayMessage() { val message = getMessage() println(message) } """.strip() # Create test file test_file = self.project_path / "Message.kt" test_file.write_text(kotlin_code) # Mock ktlint and gradle with patch.object(self.tools.ktlint, "format_file", return_value=kotlin_code): with patch.object( self.tools.gradle_api, "build_project", return_value={"success": True} ): result = await self.tools.refactor_function( { "filePath": str(test_file), "functionName": "getMessage", "refactorType": "inline", "preview": True, } ) assert result["success"] is True assert "diff" in result @pytest.mark.asyncio async def test_introduce_parameter_success(self): """Test successful parameter introduction.""" kotlin_code = """ fun greet(): String { return "Hello User" } """.strip() # Create test file test_file = self.project_path / "Greeter.kt" test_file.write_text(kotlin_code) # Mock ktlint and gradle with patch.object(self.tools.ktlint, "format_file", return_value=kotlin_code): with patch.object( self.tools.gradle_api, "build_project", return_value={"success": True} ): result = await self.tools.refactor_function( { "filePath": str(test_file), "functionName": "greet", "refactorType": "introduceParam", "paramName": "name", "paramType": "String", "preview": True, } ) assert result["success"] is True assert "diff" in result @pytest.mark.asyncio async def test_compilation_failure_handling(self): """Test handling of compilation failures.""" kotlin_code = "fun test() { invalid_syntax }" # Create test file test_file = self.project_path / "Invalid.kt" test_file.write_text(kotlin_code) # Mock ktlint to succeed but gradle to fail with patch.object(self.tools.ktlint, "format_file", return_value=kotlin_code): with patch.object( self.tools.gradle_api, "build_project", return_value={"success": False, "error": "Compilation failed: syntax error"}, ): result = await self.tools.refactor_function( { "filePath": str(test_file), "functionName": "test", "refactorType": "rename", "newName": "testRenamed", "preview": True, } ) assert result["success"] is False assert "compilation errors" in result["error"].lower() def test_file_not_found(self): """Test handling of non-existent files.""" result = asyncio.run( self.tools.refactor_function( { "filePath": "nonexistent.kt", "functionName": "test", "refactorType": "rename", "newName": "test2", } ) ) assert result["success"] is False assert "not found" in result["error"] def test_unsupported_refactor_type(self): """Test handling of unsupported refactor types.""" result = asyncio.run( self.tools.refactor_function( {"filePath": "test.kt", "functionName": "test", "refactorType": "unsupported_type"} ) ) assert result["success"] is False assert "Unsupported refactor type" in result["error"] if __name__ == "__main__": pytest.main([__file__])

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/normaltusker/kotlin-mcp-server'

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