""" tests/test_architecture_pressure_engine.py Unit tests for architecture_pressure.py: - compute_pressure scoring - band classification - requires_arch_review flag - signal scoring (count-based diminishing + boolean) - signals_summary generation """ import sys, os sys.path.insert(0, os.path.join(os.path.dirname(__file__), "../services/router")) import pytest from architecture_pressure import ( compute_pressure, classify_pressure_band, load_pressure_policy, _reload_pressure_policy, _score_signals, _signals_summary, _builtin_pressure_defaults, ) @pytest.fixture(autouse=True) def reset_policy(): _reload_pressure_policy() yield _reload_pressure_policy() @pytest.fixture def policy(): return _builtin_pressure_defaults() class TestClassifyBand: def test_score_0_is_low(self, policy): assert classify_pressure_band(0, policy) == "low" def test_score_at_low_max_is_low(self, policy): assert classify_pressure_band(20, policy) == "low" def test_score_21_is_medium(self, policy): assert classify_pressure_band(21, policy) == "medium" def test_score_at_medium_max_is_medium(self, policy): assert classify_pressure_band(45, policy) == "medium" def test_score_46_is_high(self, policy): assert classify_pressure_band(46, policy) == "high" def test_score_at_high_max_is_high(self, policy): assert classify_pressure_band(70, policy) == "high" def test_score_71_is_critical(self, policy): assert classify_pressure_band(71, policy) == "critical" def test_score_200_is_critical(self, policy): assert classify_pressure_band(200, policy) == "critical" class TestScoreSignals: def test_no_signals_zero_score(self, policy): components = { "recurrence_high_30d": 0, "recurrence_warn_30d": 0, "regressions_30d": 0, "escalations_30d": 0, "followups_created_30d": 0, "followups_overdue": 0, "drift_failures_30d": 0, "dependency_high_30d": 0, } assert _score_signals(components, policy) == 0 def test_recurrence_high_boolean(self, policy): components = { "recurrence_high_30d": 1, "recurrence_warn_30d": 0, "regressions_30d": 0, "escalations_30d": 0, "followups_created_30d": 0, "followups_overdue": 0, "drift_failures_30d": 0, "dependency_high_30d": 0, } score = _score_signals(components, policy) assert score == 20 # weight = 20 def test_recurrence_high_multiple_times_still_one_weight(self, policy): """recurrence_high_30d is a boolean — count > 1 does not multiply.""" components = { "recurrence_high_30d": 5, "recurrence_warn_30d": 0, "regressions_30d": 0, "escalations_30d": 0, "followups_created_30d": 0, "followups_overdue": 0, "drift_failures_30d": 0, "dependency_high_30d": 0, } score_5 = _score_signals(components, policy) components["recurrence_high_30d"] = 1 score_1 = _score_signals(components, policy) assert score_5 == score_1 def test_regressions_count_increases_score(self, policy): base = {"recurrence_high_30d": 0, "recurrence_warn_30d": 0, "regressions_30d": 1, "escalations_30d": 0, "followups_created_30d": 0, "followups_overdue": 0, "drift_failures_30d": 0, "dependency_high_30d": 0} s1 = _score_signals(base, policy) base["regressions_30d"] = 3 s3 = _score_signals(base, policy) assert s3 > s1 def test_followups_overdue_adds_score(self, policy): components = { "recurrence_high_30d": 0, "recurrence_warn_30d": 0, "regressions_30d": 0, "escalations_30d": 0, "followups_created_30d": 0, "followups_overdue": 2, "drift_failures_30d": 0, "dependency_high_30d": 0, } score = _score_signals(components, policy) # weight=15, first unit = 15, second = 15//2 = 7 expected = 15 + 7 assert score == expected def test_all_signals_present(self, policy): components = { "recurrence_high_30d": 1, "recurrence_warn_30d": 1, "regressions_30d": 2, "escalations_30d": 2, "followups_created_30d": 2, "followups_overdue": 2, "drift_failures_30d": 2, "dependency_high_30d": 2, } score = _score_signals(components, policy) assert score > 0 class TestSignalsSummary: def test_empty_components_no_summary(self, policy): comp = {k: 0 for k in [ "recurrence_high_30d", "recurrence_warn_30d", "regressions_30d", "escalations_30d", "followups_created_30d", "followups_overdue", "drift_failures_30d", "dependency_high_30d", ]} assert _signals_summary(comp, policy) == [] def test_recurrence_high_summary(self, policy): comp = {"recurrence_high_30d": 1, "recurrence_warn_30d": 0, "regressions_30d": 0, "escalations_30d": 0, "followups_created_30d": 0, "followups_overdue": 0, "drift_failures_30d": 0, "dependency_high_30d": 0} summaries = _signals_summary(comp, policy) assert any("High-recurrence" in s for s in summaries) def test_followups_overdue_in_summary(self, policy): comp = {"recurrence_high_30d": 0, "recurrence_warn_30d": 0, "regressions_30d": 0, "escalations_30d": 0, "followups_created_30d": 0, "followups_overdue": 3, "drift_failures_30d": 0, "dependency_high_30d": 0} summaries = _signals_summary(comp, policy) assert any("Overdue follow-ups" in s for s in summaries) class TestComputePressure: def test_no_signals_returns_low(self, policy): report = compute_pressure( "gateway", "prod", components={ "recurrence_high_30d": 0, "recurrence_warn_30d": 0, "regressions_30d": 0, "escalations_30d": 0, "followups_created_30d": 0, "followups_overdue": 0, "drift_failures_30d": 0, "dependency_high_30d": 0, }, policy=policy, ) assert report["score"] == 0 assert report["band"] == "low" assert report["requires_arch_review"] is False def test_high_pressure_sets_requires_arch_review(self, policy): report = compute_pressure( "gateway", "prod", components={ "recurrence_high_30d": 1, "regressions_30d": 3, "escalations_30d": 3, "followups_overdue": 2, "recurrence_warn_30d": 1, "followups_created_30d": 2, "drift_failures_30d": 2, "dependency_high_30d": 2, }, policy=policy, ) assert report["requires_arch_review"] is True assert report["band"] in ("high", "critical") def test_report_includes_service_and_env(self, policy): report = compute_pressure( "router", "staging", components={k: 0 for k in [ "recurrence_high_30d", "recurrence_warn_30d", "regressions_30d", "escalations_30d", "followups_created_30d", "followups_overdue", "drift_failures_30d", "dependency_high_30d", ]}, policy=policy, ) assert report["service"] == "router" assert report["env"] == "staging" def test_report_has_computed_at(self, policy): report = compute_pressure("svc", "prod", components={}, policy=policy) assert "computed_at" in report def test_missing_components_default_to_zero(self, policy): """If components dict is incomplete, missing keys default to 0.""" report = compute_pressure( "svc", "prod", components={"recurrence_high_30d": 1}, policy=policy, ) assert report["score"] >= 0 # no KeyError def test_score_is_non_negative(self, policy): report = compute_pressure("svc", "prod", components={}, policy=policy) assert report["score"] >= 0 def test_signals_summary_populated_when_signals_active(self, policy): report = compute_pressure( "svc", "prod", components={ "recurrence_high_30d": 1, "regressions_30d": 2, "escalations_30d": 0, "recurrence_warn_30d": 0, "followups_created_30d": 0, "followups_overdue": 0, "drift_failures_30d": 0, "dependency_high_30d": 0, }, policy=policy, ) assert len(report["signals_summary"]) > 0 def test_band_critical_above_70(self, policy): report = compute_pressure( "svc", "prod", components={ "recurrence_high_30d": 1, "regressions_30d": 5, "escalations_30d": 5, "followups_overdue": 5, "recurrence_warn_30d": 1, "followups_created_30d": 5, "drift_failures_30d": 5, "dependency_high_30d": 5, }, policy=policy, ) assert report["band"] == "critical" assert report["requires_arch_review"] is True def test_no_stores_with_none_components_returns_report(self, policy): """When no stores, fallback to zeros — should not raise.""" report = compute_pressure("svc", "prod", policy=policy) assert "score" in report assert "band" in report