Files
shell-speak/tests/test_analyzer.py
Auto User 95459fb4c8 fix: resolve CI test failure in output.py
- Fixed undefined 'tool' variable in display_history function
- Changed '[tool]' markup tag usage to proper Rich syntax
- All tests now pass (38/38 unit tests)
- Type checking passes with mypy --strict
2026-01-31 06:22:27 +00:00

215 lines
7.1 KiB
Python

"""Tests for the analyzer module."""
import pytest
from cli_diff_auditor.analyzer import AuditResult, DiffAuditor, FileAnalyzer
from cli_diff_auditor.diff_parser import ChangeType, DiffHunk, DiffLine, FileDiff
from cli_diff_auditor.rules import RulesLoader, Severity
class TestAuditResult:
"""Test cases for AuditResult class."""
def test_add_finding_error(self):
"""Test adding an error finding."""
result = AuditResult()
result.add_finding(type('Finding', (), {
'severity': Severity.ERROR
})())
assert result.errors_count == 1
assert result.warnings_count == 0
assert result.info_count == 0
def test_add_finding_warning(self):
"""Test adding a warning finding."""
result = AuditResult()
result.add_finding(type('Finding', (), {
'severity': Severity.WARNING
})())
assert result.errors_count == 0
assert result.warnings_count == 1
assert result.info_count == 0
def test_add_finding_info(self):
"""Test adding an info finding."""
result = AuditResult()
result.add_finding(type('Finding', (), {
'severity': Severity.INFO
})())
assert result.errors_count == 0
assert result.warnings_count == 0
assert result.info_count == 1
def test_get_summary(self):
"""Test getting the summary."""
result = AuditResult()
for _ in range(2):
result.add_finding(type('Finding', (), {'severity': Severity.ERROR})())
for _ in range(3):
result.add_finding(type('Finding', (), {'severity': Severity.WARNING})())
for _ in range(1):
result.add_finding(type('Finding', (), {'severity': Severity.INFO})())
summary = result.get_summary()
assert summary["error"] == 2
assert summary["warning"] == 3
assert summary["info"] == 1
assert summary["total"] == 6
def test_has_errors(self):
"""Test checking for errors."""
result = AuditResult()
assert result.has_errors() is False
result.add_finding(type('Finding', (), {'severity': Severity.ERROR})())
assert result.has_errors() is True
def test_has_findings(self):
"""Test checking for any findings."""
result = AuditResult()
assert result.has_findings() is False
result.add_finding(type('Finding', (), {'severity': Severity.INFO})())
assert result.has_findings() is True
class TestFileAnalyzer:
"""Test cases for FileAnalyzer class."""
def setup_method(self):
"""Set up test fixtures."""
self.rules_loader = RulesLoader()
self.rules_loader.load_builtin_rules()
self.analyzer = FileAnalyzer(self.rules_loader)
def test_analyze_file_diff_finds_debug_print(self):
"""Test that debug prints are detected."""
file_diff = FileDiff(file_path="test.py")
hunk = DiffHunk(old_start=1, old_lines=2, new_start=1, new_lines=2)
hunk.lines = [
DiffLine(line_number=1, content="print('hello')", change_type=ChangeType.ADDED),
]
file_diff.hunks.append(hunk)
findings = self.analyzer.analyze_file_diff(file_diff)
assert len(findings) == 1
assert findings[0].rule_id == "debug-print"
def test_analyze_file_diff_finds_console_log(self):
"""Test that console.log is detected."""
file_diff = FileDiff(file_path="test.js")
hunk = DiffHunk(old_start=1, old_lines=2, new_start=1, new_lines=2)
hunk.lines = [
DiffLine(line_number=1, content="console.log('test')", change_type=ChangeType.ADDED),
]
file_diff.hunks.append(hunk)
findings = self.analyzer.analyze_file_diff(file_diff)
assert len(findings) == 1
assert findings[0].rule_id == "console-log"
def test_analyze_file_diff_ignores_clean_code(self):
"""Test that clean code has no findings."""
file_diff = FileDiff(file_path="test.py")
hunk = DiffHunk(old_start=1, old_lines=2, new_start=1, new_lines=2)
hunk.lines = [
DiffLine(line_number=1, content="def hello():", change_type=ChangeType.ADDED),
DiffLine(line_number=2, content=" return 'world'", change_type=ChangeType.ADDED),
]
file_diff.hunks.append(hunk)
findings = self.analyzer.analyze_file_diff(file_diff)
assert len(findings) == 0
def test_analyze_binary_file(self):
"""Test that binary files are skipped."""
file_diff = FileDiff(file_path="image.png", is_binary=True)
hunk = DiffHunk(old_start=1, old_lines=1, new_start=1, new_lines=1)
hunk.lines = [
DiffLine(line_number=1, content="binary data", change_type=ChangeType.ADDED),
]
file_diff.hunks.append(hunk)
findings = self.analyzer.analyze_file_diff(file_diff)
assert len(findings) == 0
def test_analyze_deleted_lines(self):
"""Test that deleted lines are also analyzed."""
file_diff = FileDiff(file_path="test.py")
hunk = DiffHunk(old_start=1, old_lines=2, new_start=1, new_lines=1)
hunk.lines = [
DiffLine(line_number=1, content="print('old')", change_type=ChangeType.DELETED),
]
file_diff.hunks.append(hunk)
findings = self.analyzer.analyze_file_diff(file_diff)
assert len(findings) == 1
assert findings[0].rule_id == "debug-print"
class TestDiffAuditor:
"""Test cases for DiffAuditor class."""
def setup_method(self):
"""Set up test fixtures."""
self.auditor = DiffAuditor()
def test_get_all_rules(self):
"""Test getting all rules."""
rules = self.auditor.get_rules()
assert len(rules) > 0
assert any(r.id == "debug-print" for r in rules)
def test_get_enabled_rules(self):
"""Test getting enabled rules."""
self.auditor.disable_rules(["debug-print", "console-log"])
enabled = self.auditor.get_enabled_rules()
rule_ids = [r.id for r in enabled]
assert "debug-print" not in rule_ids
assert "console-log" not in rule_ids
def test_disable_and_enable_rules(self):
"""Test disabling and enabling rules."""
self.auditor.disable_rules(["debug-print"])
enabled = self.auditor.get_enabled_rules()
assert "debug-print" not in [r.id for r in enabled]
self.auditor.enable_rules(["debug-print"])
enabled = self.auditor.get_enabled_rules()
assert "debug-print" in [r.id for r in enabled]
def test_audit_diff_output(self):
"""Test auditing diff output directly."""
diff_output = """diff --git a/test.py b/test.py
index 1234567..89abcdef 100644
--- a/test.py
+++ b/test.py
@@ -1,2 +1,2 @@
-old
+print('debug')
"""
result = self.auditor.audit_diff_output(diff_output)
assert result.files_scanned == 1
assert result.has_findings()
assert result.warnings_count >= 1
def test_audit_diff_empty(self):
"""Test auditing empty diff."""
result = self.auditor.audit_diff_output("")
assert result.files_scanned == 0
assert not result.has_findings()