Files
ai-code-refactor-cli/tests/test_fixers.py
7000pctAUTO 3d41fb707c
Some checks failed
CI / test (push) Has been cancelled
CI / build (push) Has been cancelled
Add fixer and rule tests
2026-01-29 23:13:48 +00:00

221 lines
6.6 KiB
Python

"""Tests for code fixers."""
import pytest
from pathlib import Path
from src.analyzers.base import SeverityLevel, FindingCategory
from src.fixers import (
SQLInjectionFixer,
EvalUsageFixer,
ExceptionSwallowFixer,
MagicNumberFixer,
RedundantOperationFixer,
)
class TestSQLInjectionFixer:
"""Tests for SQL injection fixer."""
def setup_method(self):
self.fixer = SQLInjectionFixer()
def test_fixes_sql_injection(self):
code = 'cursor.execute("SELECT * FROM users WHERE name = \'" + user_input + "\'")'
finding = self._create_finding()
tree = self._parse_code(code)
result = self.fixer.fix(code, finding, tree)
assert "?" in result or '"' in result
def _create_finding(self):
from src.analyzers.base import Finding
return Finding(
rule_id="security.sql_injection",
rule_name="SQL Injection Detection",
severity=SeverityLevel.CRITICAL,
category=FindingCategory.SECURITY,
message="SQL injection detected",
suggestion="Use parameterized queries",
file_path=Path("test.py"),
line_number=1,
column=0,
)
def _parse_code(self, code):
from src.analyzers import PythonParser
parser = PythonParser()
return parser.parse(code)
class TestEvalUsageFixer:
"""Tests for eval/exec fixer."""
def setup_method(self):
self.fixer = EvalUsageFixer()
def test_comments_out_eval(self):
code = 'result = eval(user_input)'
finding = self._create_finding()
tree = self._parse_code(code)
result = self.fixer.fix(code, finding, tree)
assert "# eval(" in result
def _create_finding(self):
from src.analyzers.base import Finding
return Finding(
rule_id="security.eval_usage",
rule_name="Eval Usage Detection",
severity=SeverityLevel.CRITICAL,
category=FindingCategory.SECURITY,
message="eval detected",
suggestion="Avoid eval",
file_path=Path("test.py"),
line_number=1,
column=0,
)
def _parse_code(self, code):
from src.analyzers import PythonParser
parser = PythonParser()
return parser.parse(code)
class TestExceptionSwallowFixer:
"""Tests for exception swallowing fixer."""
def setup_method(self):
self.fixer = ExceptionSwallowFixer()
def test_adds_exception_logging(self):
code = """try:
dangerous()
except:
pass
"""
finding = self._create_finding()
tree = self._parse_code(code)
result = self.fixer.fix(code, finding, tree)
assert "logger.error" in result or "Exception as e" in result
def _create_finding(self):
from src.analyzers.base import Finding
return Finding(
rule_id="antipattern.exception_swallow",
rule_name="Exception Swallow Detection",
severity=SeverityLevel.MEDIUM,
category=FindingCategory.ANTIPATTERN,
message="Exception swallowing detected",
suggestion="Log the exception",
file_path=Path("test.py"),
line_number=2,
column=0,
)
def _parse_code(self, code):
from src.analyzers import PythonParser
parser = PythonParser()
return parser.parse(code)
class TestMagicNumberFixer:
"""Tests for magic number fixer."""
def setup_method(self):
self.fixer = MagicNumberFixer()
def test_replaces_magic_number(self):
code = "result = 42"
finding = self._create_finding()
tree = self._parse_code(code)
result = self.fixer.fix(code, finding, tree)
assert "MAGIC_NUMBER_42" in result
def _create_finding(self):
from src.analyzers.base import Finding
return Finding(
rule_id="antipattern.magic_number",
rule_name="Magic Number Detection",
severity=SeverityLevel.LOW,
category=FindingCategory.ANTIPATTERN,
message="Magic number detected",
suggestion="Define as constant",
file_path=Path("test.py"),
line_number=1,
column=0,
)
def _parse_code(self, code):
from src.analyzers import PythonParser
parser = PythonParser()
return parser.parse(code)
class TestRedundantOperationFixer:
"""Tests for redundant operation fixer."""
def setup_method(self):
self.fixer = RedundantOperationFixer()
def test_removes_redundant_list_call(self):
code = "result = list(list(my_list))"
finding = self._create_finding()
tree = self._parse_code(code)
result = self.fixer.fix(code, finding, tree)
assert "list(list(" not in result
def _create_finding(self):
from src.analyzers.base import Finding
return Finding(
rule_id="performance.redundant_operation",
rule_name="Redundant Operation Detection",
severity=SeverityLevel.LOW,
category=FindingCategory.PERFORMANCE,
message="Redundant operation detected",
suggestion="Remove redundant call",
file_path=Path("test.py"),
line_number=1,
column=0,
)
def _parse_code(self, code):
from src.analyzers import PythonParser
parser = PythonParser()
return parser.parse(code)
class TestFixerRegistry:
"""Tests for fixer registry."""
def test_get_fixer_returns_correct_fixer(self):
from src.fixers import FixerRegistry
registry = FixerRegistry()
fixer = registry.get_fixer("security.sql_injection")
assert fixer is not None
assert isinstance(fixer, SQLInjectionFixer)
def test_get_fixer_returns_none_for_unknown_rule(self):
from src.fixers import FixerRegistry
registry = FixerRegistry()
fixer = registry.get_fixer("unknown.rule_id")
assert fixer is None
def test_can_fix_checks_correctly(self):
from src.fixers import FixerRegistry
from src.analyzers.base import Finding
registry = FixerRegistry()
finding = Finding(
rule_id="security.sql_injection",
rule_name="Test",
severity=SeverityLevel.CRITICAL,
category=FindingCategory.SECURITY,
message="Test",
suggestion="Test",
file_path=Path("test.py"),
line_number=1,
column=0,
)
assert registry.can_fix(finding) is True
finding.rule_id = "unknown.rule"
assert registry.can_fix(finding) is False