Files
shell-speak/tests/test_rules.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

252 lines
6.8 KiB
Python

"""Tests for the rules module."""
import pytest
from cli_diff_auditor.rules import (
BuiltInRules,
Finding,
Rule,
RulesLoader,
Severity,
)
class TestRule:
"""Test cases for Rule class."""
def test_rule_creation(self):
"""Test creating a Rule instance."""
rule = Rule(
id="test-rule",
name="Test Rule",
description="A test rule",
pattern=r"test.*",
severity=Severity.WARNING,
auto_fix=True,
category="testing"
)
assert rule.id == "test-rule"
assert rule.name == "Test Rule"
assert rule.severity == Severity.WARNING
assert rule.auto_fix is True
assert rule.enabled is True
def test_compile_pattern(self):
"""Test compiling a rule pattern."""
rule = Rule(
id="test",
name="Test",
description="Test",
pattern=r"\bprint\s*\(",
severity=Severity.WARNING
)
compiled = rule.compile_pattern()
assert compiled.search("print('hello')") is not None
assert compiled.search("hello world") is None
def test_get_fix_pattern(self):
"""Test getting the fix pattern."""
rule = Rule(
id="test",
name="Test",
description="Test",
pattern=r"test",
severity=Severity.INFO,
auto_fix=True,
fix_pattern=r"old",
replacement="new"
)
fix_pattern = rule.get_fix_pattern()
assert fix_pattern is not None
assert fix_pattern.search("old text") is not None
class TestBuiltInRules:
"""Test cases for BuiltInRules class."""
def test_get_all_rules_returns_list(self):
"""Test that get_all_rules returns a list."""
rules = BuiltInRules.get_all_rules()
assert isinstance(rules, list)
assert len(rules) > 0
def test_rules_have_required_fields(self):
"""Test that all rules have required fields."""
rules = BuiltInRules.get_all_rules()
for rule in rules:
assert rule.id
assert rule.name
assert rule.description
assert rule.pattern
assert rule.severity
def test_debug_rules_exist(self):
"""Test that debug-related rules exist."""
rules = BuiltInRules.get_all_rules()
rule_ids = [r.id for r in rules]
assert "debug-print" in rule_ids
assert "console-log" in rule_ids
def test_security_rules_exist(self):
"""Test that security-related rules exist."""
rules = BuiltInRules.get_all_rules()
rule_ids = [r.id for r in rules]
assert "sql-injection" in rule_ids
assert "hardcoded-password" in rule_ids
assert "eval-usage" in rule_ids
def test_error_handling_rules_exist(self):
"""Test that error handling rules exist."""
rules = BuiltInRules.get_all_rules()
rule_ids = [r.id for r in rules]
assert "bare-except" in rule_ids
assert "pass-except" in rule_ids
class TestRulesLoader:
"""Test cases for RulesLoader class."""
def setup_method(self):
"""Set up test fixtures."""
self.loader = RulesLoader()
def test_load_builtin_rules(self):
"""Test loading built-in rules."""
self.loader.load_builtin_rules()
rules = self.loader.get_all_rules()
assert len(rules) > 0
def test_get_rule(self):
"""Test getting a specific rule."""
self.loader.load_builtin_rules()
rule = self.loader.get_rule("debug-print")
assert rule is not None
assert rule.id == "debug-print"
def test_get_nonexistent_rule(self):
"""Test getting a rule that doesn't exist."""
self.loader.load_builtin_rules()
rule = self.loader.get_rule("nonexistent-rule")
assert rule is None
def test_disable_rule(self):
"""Test disabling a rule."""
self.loader.load_builtin_rules()
result = self.loader.disable_rule("debug-print")
assert result is True
rule = self.loader.get_rule("debug-print")
assert rule.enabled is False
def test_enable_rule(self):
"""Test enabling a rule."""
self.loader.load_builtin_rules()
self.loader.disable_rule("debug-print")
result = self.loader.enable_rule("debug-print")
assert result is True
rule = self.loader.get_rule("debug-print")
assert rule.enabled is True
def test_get_enabled_rules(self):
"""Test getting only enabled rules."""
self.loader.load_builtin_rules()
self.loader.disable_rule("debug-print")
self.loader.disable_rule("console-log")
enabled = self.loader.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_load_from_yaml(self):
"""Test loading rules from YAML."""
self.loader.load_builtin_rules()
yaml_content = """
rules:
- id: custom-rule
name: Custom Rule
description: A custom rule
pattern: "custom.*"
severity: warning
category: custom
"""
rules = self.loader.load_from_yaml(yaml_content)
assert len(rules) == 1
assert rules[0].id == "custom-rule"
all_rules = self.loader.get_all_rules()
assert len(all_rules) > 1
def test_load_from_yaml_minimal(self):
"""Test loading rules with minimal fields."""
yaml_content = """
rules:
- id: minimal-rule
name: Minimal
description: Minimal description
pattern: "test"
severity: error
"""
rules = self.loader.load_from_yaml(yaml_content)
assert len(rules) == 1
assert rules[0].severity == Severity.ERROR
assert rules[0].auto_fix is False
assert rules[0].category == "custom"
def test_parse_rule_data_missing_required_field(self):
"""Test parsing rule data with missing required field."""
data = {
"id": "test",
"name": "Test",
"description": "Test"
}
with pytest.raises(ValueError):
self.loader._parse_rule_data(data)
class TestFinding:
"""Test cases for Finding class."""
def test_finding_creation(self):
"""Test creating a Finding instance."""
finding = Finding(
rule_id="test-rule",
rule_name="Test Rule",
severity=Severity.WARNING,
file_path="test.py",
line_number=10,
line_content="print('debug')",
message="Debug print statement detected",
fix_available=True
)
assert finding.rule_id == "test-rule"
assert finding.severity == Severity.WARNING
assert finding.line_number == 10
assert finding.fix_available is True