647ad3d49d
RED phase for Phase 0. Mirrors tests/test_audit_weak_types.py structure: - test_audit_script_exists: AUDIT_SCRIPT.is_file() sanity - test_audit_help_runs: --help exits 0 - test_audit_json_mode_emits_valid_json: --json emits valid JSON with expected fields - test_audit_default_mode_emits_human_report: default mode prints a report - test_audit_strict_mode_against_existing_baseline_passes: --strict exits 0 when current <= baseline - test_audit_strict_mode_fails_when_baseline_is_zero: --strict exits 1 when current > baseline=0 - test_audit_baseline_field_shape: --json output has expected baseline-shape fields 7 tests total. Run with: uv run pytest tests/test_audit_dataclass_coverage.py --timeout=30 NOTE: 6 of 7 tests fail at this commit (audit script not yet implemented). This is the RED phase; GREEN comes in the next commit.
98 lines
3.2 KiB
Python
98 lines
3.2 KiB
Python
"""Tests for scripts/audit_dataclass_coverage.py
|
|
|
|
The audit counts `dict[str, Any]` and `list[dict[...]]` annotations that
|
|
remain outside the 5 promoted dataclass sites (mcp_tool_specs, openai_schemas,
|
|
provider_state, log_registry.Session, api_hooks.WebSocketMessage).
|
|
|
|
Mirrors tests/test_audit_weak_types.py structure.
|
|
|
|
CONVENTION: 1-space indentation. NO COMMENTS.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import subprocess
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
|
|
REPO_ROOT = Path(__file__).resolve().parents[1]
|
|
AUDIT_SCRIPT = REPO_ROOT / "scripts" / "audit_dataclass_coverage.py"
|
|
BASELINE_FILE = REPO_ROOT / "scripts" / "audit_dataclass_coverage.baseline.json"
|
|
|
|
|
|
def _run_audit(*args: str) -> subprocess.CompletedProcess[str]:
|
|
return subprocess.run(
|
|
[sys.executable, str(AUDIT_SCRIPT), *args],
|
|
cwd=str(REPO_ROOT),
|
|
capture_output=True,
|
|
text=True,
|
|
timeout=60,
|
|
)
|
|
|
|
|
|
def test_audit_script_exists() -> None:
|
|
assert AUDIT_SCRIPT.is_file(), f"audit script missing: {AUDIT_SCRIPT}"
|
|
|
|
|
|
def test_audit_help_runs() -> None:
|
|
result = _run_audit("--help")
|
|
assert result.returncode == 0
|
|
assert "audit" in result.stdout.lower()
|
|
|
|
|
|
def test_audit_json_mode_emits_valid_json() -> None:
|
|
result = _run_audit("--json")
|
|
assert result.returncode == 0, f"audit --json failed: {result.stderr}"
|
|
payload = json.loads(result.stdout)
|
|
assert "files_scanned" in payload
|
|
assert "total_weak" in payload
|
|
assert "by_category" in payload
|
|
assert isinstance(payload["total_weak"], int)
|
|
assert payload["total_weak"] >= 0
|
|
|
|
|
|
def test_audit_default_mode_emits_human_report() -> None:
|
|
result = _run_audit()
|
|
assert result.returncode == 0, f"audit default mode failed: {result.stderr}"
|
|
assert "Dataclass Coverage Audit" in result.stdout or "dataclass" in result.stdout.lower()
|
|
|
|
|
|
def test_audit_strict_mode_against_existing_baseline_passes() -> None:
|
|
if not BASELINE_FILE.is_file():
|
|
pytest.skip("baseline not yet generated; skip --strict assertion")
|
|
result = _run_audit("--strict", "--baseline", str(BASELINE_FILE))
|
|
assert result.returncode == 0, (
|
|
f"audit --strict failed (current count > baseline): {result.stderr}"
|
|
)
|
|
assert "STRICT OK" in result.stdout
|
|
|
|
|
|
def test_audit_strict_mode_fails_when_baseline_is_zero() -> None:
|
|
tmp_baseline = REPO_ROOT / "tests" / "artifacts" / "tier2_state" / "any_type_componentization_20260621" / "_zero_baseline.json"
|
|
tmp_baseline.parent.mkdir(parents=True, exist_ok=True)
|
|
tmp_baseline.write_text(json.dumps({"total_weak": 0}), encoding="utf-8")
|
|
try:
|
|
result = _run_audit("--strict", "--baseline", str(tmp_baseline))
|
|
assert result.returncode == 1, "audit --strict should fail when current > baseline=0"
|
|
assert "STRICT" in result.stderr or "regression" in result.stderr.lower()
|
|
finally:
|
|
if tmp_baseline.exists():
|
|
tmp_baseline.unlink()
|
|
|
|
|
|
def test_audit_baseline_field_shape() -> None:
|
|
result = _run_audit("--json")
|
|
assert result.returncode == 0
|
|
payload = json.loads(result.stdout)
|
|
assert "total_weak" in payload
|
|
assert "files_with_findings" in payload
|
|
assert "by_category" in payload
|
|
assert "by_file" in payload
|
|
assert isinstance(payload["by_file"], list)
|
|
if payload["by_file"]:
|
|
entry = payload["by_file"][0]
|
|
assert "filename" in entry
|
|
assert "weak_count" in entry |