feat(system): test(prax): improve line coverage on handler files

Co-Authored-By: @devpulse <devpulse@aipass>
This commit is contained in:
AIOSAI
2026-04-26 02:26:29 -07:00
co-authored by @devpulse
parent 5928b7840c
commit 85d2e86c29
4 changed files with 132 additions and 249 deletions
+15
View File
@@ -476,6 +476,21 @@
"file": "tests/test_operations.py",
"standard": "encapsulation",
"reason": "Unit tests must import handlers directly to test them in isolation. _load_ops() imports operations handler for unit testing. Same pattern as test_logging_handlers.py."
},
{
"file": "tests/test_filesystem_handler.py",
"standard": "architecture",
"reason": "Test file lives in tests/ by convention, not in the 3-layer apps/ structure. This is standard for all prax test files."
},
{
"file": "tests/test_filesystem_handler.py",
"standard": "log_structure",
"reason": "False positive — /home/ references are test fixture path strings (e.g. Path('/home/user/modules/logger.py')), not real log config."
},
{
"file": "tests/test_filesystem_handler.py",
"standard": "documentation",
"reason": "Test helper functions use pytest naming conventions. Internal test stubs do not require docstrings."
}
],
"notes": {
@@ -19,8 +19,30 @@ import sys
from pathlib import Path
from unittest.mock import MagicMock, patch, mock_open as _mock_file_open
import pytest
_mopen = _mock_file_open
_INJECTED_MODULES = [
"watchdog",
"watchdog.events",
"aipass.prax.apps.handlers.monitoring.event_queue",
"aipass.prax.apps.handlers.monitoring.branch_detector",
"aipass.prax.apps.handlers.monitoring.monitoring_filters",
"aipass.prax.apps.handlers.monitoring.filesystem_handler",
]
@pytest.fixture(autouse=True)
def _cleanup_injected_modules():
"""Remove mocked monitoring modules from sys.modules after each test."""
saved = {k: sys.modules[k] for k in _INJECTED_MODULES if k in sys.modules}
yield
for k in _INJECTED_MODULES:
sys.modules.pop(k, None)
for k, v in saved.items():
sys.modules[k] = v
# =============================================
# MODULE IMPORT HELPER
+9 -2
View File
@@ -1048,11 +1048,18 @@ class TestInitializePositionsAdditional:
log_file = tmp_path / "bad.log"
log_file.write_text("content\n", encoding="utf-8")
original_stat = Path.stat
def failing_stat(self_path, *args, **kwargs):
"""Fail stat only for .log files, not directory existence."""
if str(self_path).endswith(".log"):
raise OSError("stat failed")
return original_stat(self_path, *args, **kwargs)
with (
patch.object(mod, "get_system_logs_dir", return_value=tmp_path),
patch.object(Path, "stat", side_effect=OSError("stat failed")),
patch.object(Path, "stat", failing_stat),
):
# Should not raise
watcher.initialize_positions()
assert str(log_file) not in watcher.log_positions
+86 -247
View File
@@ -8,6 +8,9 @@
# Modified: 2026-04-26
# =============================================
# seedgo:bypass standard=architecture reason="test files live in tests/, not apps/"
# seedgo:bypass standard=encapsulation reason="tests import handlers directly for unit testing"
import types
import pytest
@@ -30,9 +33,7 @@ def _mock_infrastructure(monkeypatch):
mock_json_handler = MagicMock()
mock_json_handler.log_operation = MagicMock(return_value=True)
mock_ignore_handler = MagicMock()
mock_ignore_handler.get_audit_ignore_patterns = MagicMock(
return_value=[]
)
mock_ignore_handler.get_audit_ignore_patterns = MagicMock(return_value=[])
mock_scan_branch = MagicMock(return_value=None)
# -- prax ---------------------------------------------------------------
@@ -48,9 +49,7 @@ def _mock_infrastructure(monkeypatch):
# -- seedgo json handler ------------------------------------------------
json_pkg = MagicMock()
json_pkg.json_handler = mock_json_handler
monkeypatch.setitem(
sys.modules, "aipass.seedgo.apps.handlers.json", json_pkg
)
monkeypatch.setitem(sys.modules, "aipass.seedgo.apps.handlers.json", json_pkg)
json_mod = MagicMock()
json_mod.log_operation = mock_json_handler.log_operation
monkeypatch.setitem(
@@ -62,9 +61,7 @@ def _mock_infrastructure(monkeypatch):
# -- bypass handler -----------------------------------------------------
bypass_pkg = MagicMock()
bypass_pkg.ignore_handler = mock_ignore_handler
monkeypatch.setitem(
sys.modules, "aipass.seedgo.apps.handlers.bypass", bypass_pkg
)
monkeypatch.setitem(sys.modules, "aipass.seedgo.apps.handlers.bypass", bypass_pkg)
monkeypatch.setitem(
sys.modules,
"aipass.seedgo.apps.handlers.bypass.ignore_handler",
@@ -87,13 +84,13 @@ def _mock_infrastructure(monkeypatch):
scanner_mod,
)
# -- audit package (must be a real module with __path__ so
# submodule imports like audit.audit_display work) --------------------
# -- audit package (must be a real module with __path__ pointing to the
# actual directory so submodule imports like audit.audit_display work)
audit_pkg = types.ModuleType("aipass.seedgo.apps.handlers.audit")
audit_pkg.__path__ = [] # type: ignore[attr-defined]
monkeypatch.setitem(
sys.modules, "aipass.seedgo.apps.handlers.audit", audit_pkg
)
audit_pkg.__path__ = [ # type: ignore[attr-defined]
str(Path(__file__).resolve().parents[1] / "apps" / "handlers" / "audit")
]
monkeypatch.setitem(sys.modules, "aipass.seedgo.apps.handlers.audit", audit_pkg)
# Force re-imports so modules pick up fresh mocks
for mod_name in [
@@ -201,10 +198,7 @@ class TestRenderViolations:
)
mock_con = MagicMock()
violations = [
{"path": f"/file{i}.py", "score": 10, "issues": []}
for i in range(8)
]
violations = [{"path": f"/file{i}.py", "score": 10, "issues": []} for i in range(8)]
_render_violations("naming", violations, mock_con)
calls = [str(c) for c in mock_con.print.call_args_list]
assert any("3 more" in c for c in calls)
@@ -216,10 +210,7 @@ class TestRenderViolations:
)
mock_con = MagicMock()
violations = [
{"path": f"/file{i}.py", "score": 10, "issues": []}
for i in range(5)
]
violations = [{"path": f"/file{i}.py", "score": 10, "issues": []} for i in range(5)]
_render_violations("naming", violations, mock_con)
calls = [str(c) for c in mock_con.print.call_args_list]
assert not any("more" in c for c in calls)
@@ -246,15 +237,7 @@ class TestRenderArchitectureViolations:
)
mock_con = MagicMock()
audit_result = {
"results": {
"architecture": {
"checks": [
{"passed": True, "name": "Dir: apps"}
]
}
}
}
audit_result = {"results": {"architecture": {"checks": [{"passed": True, "name": "Dir: apps"}]}}}
_render_architecture_violations(audit_result, mock_con)
assert mock_con.print.call_count == 0
@@ -273,9 +256,7 @@ class TestRenderArchitectureViolations:
"message": "x",
},
]
audit_result = {
"results": {"architecture": {"checks": checks}}
}
audit_result = {"results": {"architecture": {"checks": checks}}}
_render_architecture_violations(audit_result, mock_con)
calls = [str(c) for c in mock_con.print.call_args_list]
assert any("ARCHITECTURE VIOLATIONS" in c for c in calls)
@@ -295,9 +276,7 @@ class TestRenderArchitectureViolations:
"message": "x",
},
]
audit_result = {
"results": {"architecture": {"checks": checks}}
}
audit_result = {"results": {"architecture": {"checks": checks}}}
_render_architecture_violations(audit_result, mock_con)
calls = [str(c) for c in mock_con.print.call_args_list]
assert any("Missing files" in c for c in calls)
@@ -316,9 +295,7 @@ class TestRenderArchitectureViolations:
"message": "Something wrong",
},
]
audit_result = {
"results": {"architecture": {"checks": checks}}
}
audit_result = {"results": {"architecture": {"checks": checks}}}
_render_architecture_violations(audit_result, mock_con)
calls = [str(c) for c in mock_con.print.call_args_list]
assert any("Something wrong" in c for c in calls)
@@ -330,13 +307,8 @@ class TestRenderArchitectureViolations:
)
mock_con = MagicMock()
checks = [
{"passed": False, "name": f"Dir: dir{i}"}
for i in range(7)
]
audit_result = {
"results": {"architecture": {"checks": checks}}
}
checks = [{"passed": False, "name": f"Dir: dir{i}"} for i in range(7)]
audit_result = {"results": {"architecture": {"checks": checks}}}
_render_architecture_violations(audit_result, mock_con)
calls = [str(c) for c in mock_con.print.call_args_list]
assert any("2 more" in c for c in calls)
@@ -348,13 +320,8 @@ class TestRenderArchitectureViolations:
)
mock_con = MagicMock()
checks = [
{"passed": False, "name": f"File: file{i}.py"}
for i in range(8)
]
audit_result = {
"results": {"architecture": {"checks": checks}}
}
checks = [{"passed": False, "name": f"File: file{i}.py"} for i in range(8)]
audit_result = {"results": {"architecture": {"checks": checks}}}
_render_architecture_violations(audit_result, mock_con)
calls = [str(c) for c in mock_con.print.call_args_list]
assert any("3 more" in c for c in calls)
@@ -385,9 +352,7 @@ class TestRenderArchitectureViolations:
"message": "Missing config",
},
]
audit_result = {
"results": {"architecture": {"checks": checks}}
}
audit_result = {"results": {"architecture": {"checks": checks}}}
_render_architecture_violations(audit_result, mock_con)
calls = [str(c) for c in mock_con.print.call_args_list]
assert any("Missing directories" in c for c in calls)
@@ -405,9 +370,7 @@ class TestRenderTypeErrors:
)
mock_con = MagicMock()
_render_type_errors(
{"type_errors": 0, "files_checked": 0}, mock_con
)
_render_type_errors({"type_errors": 0, "files_checked": 0}, mock_con)
assert mock_con.print.call_count == 0
def test_no_type_errors_with_files_checked(self):
@@ -417,9 +380,7 @@ class TestRenderTypeErrors:
)
mock_con = MagicMock()
_render_type_errors(
{"type_errors": 0, "files_checked": 5}, mock_con
)
_render_type_errors({"type_errors": 0, "files_checked": 5}, mock_con)
calls = [str(c) for c in mock_con.print.call_args_list]
assert any("No type errors" in c for c in calls)
@@ -517,9 +478,7 @@ class TestRenderTestMap:
)
mock_con = MagicMock()
_render_test_map(
{"test_map": {"total_functions": 0}}, mock_con
)
_render_test_map({"test_map": {"total_functions": 0}}, mock_con)
assert mock_con.print.call_count == 0
def test_test_map_with_data(self):
@@ -564,9 +523,7 @@ class TestRenderDeprecatedPatterns:
)
mock_con = MagicMock()
_render_deprecated_patterns(
{"deprecated_patterns": []}, mock_con
)
_render_deprecated_patterns({"deprecated_patterns": []}, mock_con)
assert mock_con.print.call_count == 0
def test_with_patterns(self):
@@ -582,9 +539,7 @@ class TestRenderDeprecatedPatterns:
"message": "Rename DOCUMENTS/ to docs/",
},
]
_render_deprecated_patterns(
{"deprecated_patterns": patterns}, mock_con
)
_render_deprecated_patterns({"deprecated_patterns": patterns}, mock_con)
calls = [str(c) for c in mock_con.print.call_args_list]
assert any("DEPRECATED PATTERNS" in c for c in calls)
assert any("DOCUMENTS" in c for c in calls)
@@ -635,9 +590,7 @@ class TestPrintBranchSummary:
"name": branch_name,
"path": "/fake/path",
},
"scores": scores
if scores is not None
else {"architecture": 90, "naming": 80},
"scores": scores if scores is not None else {"architecture": 90, "naming": 80},
"average": average,
"files_checked": files_checked,
"results": results if results is not None else {},
@@ -661,9 +614,7 @@ class TestPrintBranchSummary:
print_branch_summary,
)
result = self._make_audit_result(
scores={"architecture": 95, "naming": 92}, average=93
)
result = self._make_audit_result(scores={"architecture": 95, "naming": 92}, average=93)
print_branch_summary(result)
def test_medium_scores(self):
@@ -672,9 +623,7 @@ class TestPrintBranchSummary:
print_branch_summary,
)
result = self._make_audit_result(
scores={"architecture": 80, "naming": 76}, average=78
)
result = self._make_audit_result(scores={"architecture": 80, "naming": 76}, average=78)
print_branch_summary(result)
def test_low_scores(self):
@@ -683,9 +632,7 @@ class TestPrintBranchSummary:
print_branch_summary,
)
result = self._make_audit_result(
scores={"architecture": 50, "naming": 60}, average=55
)
result = self._make_audit_result(scores={"architecture": 50, "naming": 60}, average=55)
print_branch_summary(result)
def test_odd_number_of_scores(self):
@@ -895,9 +842,7 @@ class TestPrintSystemSummary:
return {
"branch": {"name": name},
"average": avg,
"scores": scores
if scores is not None
else {"architecture": avg, "naming": avg},
"scores": scores if scores is not None else {"architecture": avg, "naming": avg},
"type_errors": type_errors,
}
@@ -977,12 +922,8 @@ class TestPrintSystemSummary:
)
results = [
self._make_result(
"a", 60, scores={"arch": 50, "naming": 70}
),
self._make_result(
"b", 80, scores={"arch": 90, "naming": 70}
),
self._make_result("a", 60, scores={"arch": 50, "naming": 70}),
self._make_result("b", 80, scores={"arch": 90, "naming": 70}),
]
print_system_summary(results)
@@ -1051,9 +992,7 @@ class TestDiscoverCheckers:
standards_dir = tmp_path / "standards"
standards_dir.mkdir()
checker_file = standards_dir / "broken_check.py"
checker_file.write_text(
"raise RuntimeError('broken')\n", encoding="utf-8"
)
checker_file.write_text("raise RuntimeError('broken')\n", encoding="utf-8")
result = discover_checkers(standards_dir)
assert "broken" not in result
@@ -1135,9 +1074,7 @@ class TestCollectPyFiles:
(apps_dir / "module.py").write_text("pass", encoding="utf-8")
subdir = apps_dir / "handlers"
subdir.mkdir()
(subdir / "handler.py").write_text(
"pass", encoding="utf-8"
)
(subdir / "handler.py").write_text("pass", encoding="utf-8")
result = _collect_py_files(tmp_path)
names = [f["name"] for f in result]
assert "module.py" in names
@@ -1148,9 +1085,7 @@ class TestCollectPyFiles:
"""Files matching ignore patterns are excluded."""
import sys
mock_ign = sys.modules[
"aipass.seedgo.apps.handlers.bypass"
].ignore_handler
mock_ign = sys.modules["aipass.seedgo.apps.handlers.bypass"].ignore_handler
mock_ign.get_audit_ignore_patterns.return_value = ["test_"]
from aipass.seedgo.apps.handlers.audit.branch_audit import (
@@ -1159,12 +1094,8 @@ class TestCollectPyFiles:
apps_dir = tmp_path / "apps"
apps_dir.mkdir()
(apps_dir / "module.py").write_text(
"pass", encoding="utf-8"
)
(apps_dir / "test_module.py").write_text(
"pass", encoding="utf-8"
)
(apps_dir / "module.py").write_text("pass", encoding="utf-8")
(apps_dir / "test_module.py").write_text("pass", encoding="utf-8")
result = _collect_py_files(tmp_path)
names = [f["name"] for f in result]
assert "module.py" in names
@@ -1305,9 +1236,7 @@ class TestRunAllFiles:
)
checker.FILE_FILTER = None
files = [{"file": "/foo.py", "name": "foo.py"}]
violations, scores = _run_all_files(
checker, "naming", files, []
)
violations, scores = _run_all_files(checker, "naming", files, [])
assert len(scores) == 1
assert scores[0] == 90
@@ -1318,14 +1247,10 @@ class TestRunAllFiles:
)
checker = MagicMock()
checker.check_module = MagicMock(
side_effect=RuntimeError("boom")
)
checker.check_module = MagicMock(side_effect=RuntimeError("boom"))
checker.FILE_FILTER = None
files = [{"file": "/foo.py", "name": "foo.py"}]
violations, scores = _run_all_files(
checker, "naming", files, []
)
violations, scores = _run_all_files(checker, "naming", files, [])
assert violations == []
assert scores == []
@@ -1350,9 +1275,7 @@ class TestRunAllFiles:
{"file": "/handler.py", "name": "handler.py"},
{"file": "/module.py", "name": "module.py"},
]
violations, scores = _run_all_files(
checker, "naming", files, []
)
violations, scores = _run_all_files(checker, "naming", files, [])
assert checker.check_module.call_count == 1
def test_skipped_checks_excluded(self):
@@ -1376,9 +1299,7 @@ class TestRunAllFiles:
)
checker.FILE_FILTER = None
files = [{"file": "/foo.py", "name": "foo.py"}]
violations, scores = _run_all_files(
checker, "naming", files, []
)
violations, scores = _run_all_files(checker, "naming", files, [])
assert scores == []
def test_failing_checks_collected(self):
@@ -1400,9 +1321,7 @@ class TestRunAllFiles:
)
checker.FILE_FILTER = None
files = [{"file": "/bad.py", "name": "bad.py"}]
violations, scores = _run_all_files(
checker, "naming", files, []
)
violations, scores = _run_all_files(checker, "naming", files, [])
assert len(violations) == 1
assert violations[0]["score"] == 40
assert "Bad naming" in violations[0]["issues"]
@@ -1444,9 +1363,7 @@ class TestLoadDiagnosticsChecker:
)
mock_spec = MagicMock()
mock_spec.loader.exec_module.side_effect = RuntimeError(
"fail"
)
mock_spec.loader.exec_module.side_effect = RuntimeError("fail")
with (
patch("pathlib.Path.exists", return_value=True),
patch(
@@ -1519,9 +1436,7 @@ def _make_checker(
"score": 100,
"checks": [],
}
checker.check_module = MagicMock(
return_value=check_module_result or default_mod
)
checker.check_module = MagicMock(return_value=check_module_result or default_mod)
else:
del checker.check_module
@@ -1531,16 +1446,12 @@ def _make_checker(
"score": 100,
"checks": [],
}
checker.check_branch = MagicMock(
return_value=check_branch_result or default_br
)
checker.check_branch = MagicMock(return_value=check_branch_result or default_br)
else:
del checker.check_branch
if has_post:
checker.check_branch_post = MagicMock(
return_value=post_result or ([], [])
)
checker.check_branch_post = MagicMock(return_value=post_result or ([], []))
else:
del checker.check_branch_post
@@ -1566,9 +1477,7 @@ class TestAuditBranch:
"_load_diagnostics_checker",
lambda: None,
)
monkeypatch.setattr(
branch_audit, "scan_branch", lambda p: None
)
monkeypatch.setattr(branch_audit, "scan_branch", lambda p: None)
result = branch_audit.audit_branch(branch, [])
assert result["branch"] == branch
@@ -1600,16 +1509,12 @@ class TestAuditBranch:
"_load_diagnostics_checker",
lambda: None,
)
monkeypatch.setattr(
branch_audit, "scan_branch", lambda p: None
)
monkeypatch.setattr(branch_audit, "scan_branch", lambda p: None)
result = branch_audit.audit_branch(branch, [])
assert result["scores"]["dead_code"] == 85
def test_branch_level_checker_exception(
self, tmp_path, monkeypatch
):
def test_branch_level_checker_exception(self, tmp_path, monkeypatch):
"""Branch-level checker that raises produces score 0."""
from aipass.seedgo.apps.handlers.audit import branch_audit
@@ -1630,17 +1535,13 @@ class TestAuditBranch:
"_load_diagnostics_checker",
lambda: None,
)
monkeypatch.setattr(
branch_audit, "scan_branch", lambda p: None
)
monkeypatch.setattr(branch_audit, "scan_branch", lambda p: None)
result = branch_audit.audit_branch(branch, [])
assert result["scores"]["broken"] == 0
assert "error" in result["results"]["broken"]
def test_entry_point_checker_exception(
self, tmp_path, monkeypatch
):
def test_entry_point_checker_exception(self, tmp_path, monkeypatch):
"""Entry-point checker that raises produces score 0."""
from aipass.seedgo.apps.handlers.audit import branch_audit
@@ -1657,9 +1558,7 @@ class TestAuditBranch:
"_load_diagnostics_checker",
lambda: None,
)
monkeypatch.setattr(
branch_audit, "scan_branch", lambda p: None
)
monkeypatch.setattr(branch_audit, "scan_branch", lambda p: None)
result = branch_audit.audit_branch(branch, [])
assert result["scores"]["naming"] == 0
@@ -1671,9 +1570,7 @@ class TestAuditBranch:
branch, branch_path = _setup_branch(tmp_path)
apps_dir = Path(branch_path) / "apps"
(apps_dir / "other.py").write_text(
"pass", encoding="utf-8"
)
(apps_dir / "other.py").write_text("pass", encoding="utf-8")
checker = _make_checker(
scope="all_files",
@@ -1695,24 +1592,18 @@ class TestAuditBranch:
"_load_diagnostics_checker",
lambda: None,
)
monkeypatch.setattr(
branch_audit, "scan_branch", lambda p: None
)
monkeypatch.setattr(branch_audit, "scan_branch", lambda p: None)
result = branch_audit.audit_branch(branch, [])
assert result["scores"]["naming"] == 80
def test_all_files_with_violations(
self, tmp_path, monkeypatch
):
def test_all_files_with_violations(self, tmp_path, monkeypatch):
"""all_files scope with failing checks updates results."""
from aipass.seedgo.apps.handlers.audit import branch_audit
branch, branch_path = _setup_branch(tmp_path)
apps_dir = Path(branch_path) / "apps"
(apps_dir / "bad.py").write_text(
"pass", encoding="utf-8"
)
(apps_dir / "bad.py").write_text("pass", encoding="utf-8")
def check_side_effect(path, bypass_rules=None):
"""Return different results based on path."""
@@ -1747,9 +1638,7 @@ class TestAuditBranch:
"_load_diagnostics_checker",
lambda: None,
)
monkeypatch.setattr(
branch_audit, "scan_branch", lambda p: None
)
monkeypatch.setattr(branch_audit, "scan_branch", lambda p: None)
result = branch_audit.audit_branch(branch, [])
assert "naming_violations" in result
@@ -1780,26 +1669,20 @@ class TestAuditBranch:
"_load_diagnostics_checker",
lambda: None,
)
monkeypatch.setattr(
branch_audit, "scan_branch", lambda p: None
)
monkeypatch.setattr(branch_audit, "scan_branch", lambda p: None)
result = branch_audit.audit_branch(branch, [])
# Post check: (100 + 50) / 2 = 75
assert result["scores"]["naming"] == 75
assert len(result["naming_violations"]) == 1
def test_post_check_raises_exception(
self, tmp_path, monkeypatch
):
def test_post_check_raises_exception(self, tmp_path, monkeypatch):
"""check_branch_post that raises is caught."""
from aipass.seedgo.apps.handlers.audit import branch_audit
branch, _ = _setup_branch(tmp_path)
checker = _make_checker(has_post=True)
checker.check_branch_post.side_effect = RuntimeError(
"fail"
)
checker.check_branch_post.side_effect = RuntimeError("fail")
monkeypatch.setattr(
branch_audit,
"discover_checkers",
@@ -1810,16 +1693,12 @@ class TestAuditBranch:
"_load_diagnostics_checker",
lambda: None,
)
monkeypatch.setattr(
branch_audit, "scan_branch", lambda p: None
)
monkeypatch.setattr(branch_audit, "scan_branch", lambda p: None)
result = branch_audit.audit_branch(branch, [])
assert result["scores"]["naming"] == 100
def test_diagnostics_checker_added(
self, tmp_path, monkeypatch
):
def test_diagnostics_checker_added(self, tmp_path, monkeypatch):
"""Diagnostics checker loaded and added."""
from aipass.seedgo.apps.handlers.audit import branch_audit
@@ -1847,16 +1726,12 @@ class TestAuditBranch:
"_load_diagnostics_checker",
lambda: diag_mod,
)
monkeypatch.setattr(
branch_audit, "scan_branch", lambda p: None
)
monkeypatch.setattr(branch_audit, "scan_branch", lambda p: None)
result = branch_audit.audit_branch(branch, [])
assert "diagnostics" in result["scores"]
def test_deprecated_documents_dir(
self, tmp_path, monkeypatch
):
def test_deprecated_documents_dir(self, tmp_path, monkeypatch):
"""DOCUMENTS/ directory detected as deprecated."""
from aipass.seedgo.apps.handlers.audit import branch_audit
@@ -1873,18 +1748,14 @@ class TestAuditBranch:
"_load_diagnostics_checker",
lambda: None,
)
monkeypatch.setattr(
branch_audit, "scan_branch", lambda p: None
)
monkeypatch.setattr(branch_audit, "scan_branch", lambda p: None)
result = branch_audit.audit_branch(branch, [])
assert len(result["deprecated_patterns"]) == 1
dep = result["deprecated_patterns"][0]
assert dep["old"] == "DOCUMENTS/"
def test_no_deprecated_without_documents(
self, tmp_path, monkeypatch
):
def test_no_deprecated_without_documents(self, tmp_path, monkeypatch):
"""No deprecated patterns without DOCUMENTS/."""
from aipass.seedgo.apps.handlers.audit import branch_audit
@@ -1899,9 +1770,7 @@ class TestAuditBranch:
"_load_diagnostics_checker",
lambda: None,
)
monkeypatch.setattr(
branch_audit, "scan_branch", lambda p: None
)
monkeypatch.setattr(branch_audit, "scan_branch", lambda p: None)
result = branch_audit.audit_branch(branch, [])
assert result["deprecated_patterns"] == []
@@ -1959,9 +1828,7 @@ class TestAuditBranch:
result = branch_audit.audit_branch(branch, [])
assert result["test_map"] == scan_result
def test_no_checkers_zero_average(
self, tmp_path, monkeypatch
):
def test_no_checkers_zero_average(self, tmp_path, monkeypatch):
"""No checkers returns average 0."""
from aipass.seedgo.apps.handlers.audit import branch_audit
@@ -1976,16 +1843,12 @@ class TestAuditBranch:
"_load_diagnostics_checker",
lambda: None,
)
monkeypatch.setattr(
branch_audit, "scan_branch", lambda p: None
)
monkeypatch.setattr(branch_audit, "scan_branch", lambda p: None)
result = branch_audit.audit_branch(branch, [])
assert result["average"] == 0
def test_implicit_branch_level(
self, tmp_path, monkeypatch
):
def test_implicit_branch_level(self, tmp_path, monkeypatch):
"""Checker without check_module treated as branch-level."""
from aipass.seedgo.apps.handlers.audit import branch_audit
@@ -2010,9 +1873,7 @@ class TestAuditBranch:
"_load_diagnostics_checker",
lambda: None,
)
monkeypatch.setattr(
branch_audit, "scan_branch", lambda p: None
)
monkeypatch.setattr(branch_audit, "scan_branch", lambda p: None)
result = branch_audit.audit_branch(branch, [])
assert result["scores"]["implicit"] == 75
@@ -2029,25 +1890,19 @@ class TestAuditBranch:
captured["value"] = pack_path
return {}
monkeypatch.setattr(
branch_audit, "discover_checkers", mock_discover
)
monkeypatch.setattr(branch_audit, "discover_checkers", mock_discover)
monkeypatch.setattr(
branch_audit,
"_load_diagnostics_checker",
lambda: None,
)
monkeypatch.setattr(
branch_audit, "scan_branch", lambda p: None
)
monkeypatch.setattr(branch_audit, "scan_branch", lambda p: None)
pack = tmp_path / "custom_standards"
branch_audit.audit_branch(branch, [], pack_path=pack)
assert captured["value"] == pack
def test_diagnostics_not_duplicated(
self, tmp_path, monkeypatch
):
def test_diagnostics_not_duplicated(self, tmp_path, monkeypatch):
"""Existing diagnostics not overwritten by loader."""
from aipass.seedgo.apps.handlers.audit import branch_audit
@@ -2076,16 +1931,12 @@ class TestAuditBranch:
"_load_diagnostics_checker",
lambda: different,
)
monkeypatch.setattr(
branch_audit, "scan_branch", lambda p: None
)
monkeypatch.setattr(branch_audit, "scan_branch", lambda p: None)
result = branch_audit.audit_branch(branch, [])
assert result["scores"]["diagnostics"] == 80
def test_branch_level_violations_extraction(
self, tmp_path, monkeypatch
):
def test_branch_level_violations_extraction(self, tmp_path, monkeypatch):
"""Branch-level results have violations extracted."""
from aipass.seedgo.apps.handlers.audit import branch_audit
@@ -2123,16 +1974,12 @@ class TestAuditBranch:
"_load_diagnostics_checker",
lambda: None,
)
monkeypatch.setattr(
branch_audit, "scan_branch", lambda p: None
)
monkeypatch.setattr(branch_audit, "scan_branch", lambda p: None)
result = branch_audit.audit_branch(branch, [])
assert len(result["dead_code_violations"]) == 1
def test_output_diagnostics_fields(
self, tmp_path, monkeypatch
):
def test_output_diagnostics_fields(self, tmp_path, monkeypatch):
"""Output includes type_errors and type_error_files."""
from aipass.seedgo.apps.handlers.audit import branch_audit
@@ -2159,19 +2006,13 @@ class TestAuditBranch:
"_load_diagnostics_checker",
lambda: None,
)
monkeypatch.setattr(
branch_audit, "scan_branch", lambda p: None
)
monkeypatch.setattr(branch_audit, "scan_branch", lambda p: None)
result = branch_audit.audit_branch(branch, [])
assert result["type_errors"] == 3
assert result["type_error_files"] == [
{"file": "a.py", "errors": 3}
]
assert result["type_error_files"] == [{"file": "a.py", "errors": 3}]
def test_post_check_empty_scores(
self, tmp_path, monkeypatch
):
def test_post_check_empty_scores(self, tmp_path, monkeypatch):
"""Post-check with empty scores does not change score."""
from aipass.seedgo.apps.handlers.audit import branch_audit
@@ -2190,9 +2031,7 @@ class TestAuditBranch:
"_load_diagnostics_checker",
lambda: None,
)
monkeypatch.setattr(
branch_audit, "scan_branch", lambda p: None
)
monkeypatch.setattr(branch_audit, "scan_branch", lambda p: None)
result = branch_audit.audit_branch(branch, [])
assert result["scores"]["naming"] == 100