Add fixer and rule tests
This commit is contained in:
220
tests/test_fixers.py
Normal file
220
tests/test_fixers.py
Normal file
@@ -0,0 +1,220 @@
|
||||
"""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
|
||||
Reference in New Issue
Block a user