From f4998b3eeef907ce4562fce4cdd8b98607fa9c57 Mon Sep 17 00:00:00 2001 From: Your Name Date: Mon, 27 Apr 2026 15:06:58 +0800 Subject: [PATCH] =?UTF-8?q?fix(test):=20=E4=BF=AE=20P3.4=20governance=5Fag?= =?UTF-8?q?ent=20=E5=8A=A0=E7=AC=AC=205=20=E9=A0=85=20slo=5Fcompliance=20?= =?UTF-8?q?=E5=BE=8C=E6=97=A2=E6=9C=89=E6=B8=AC=E8=A9=A6=E5=B0=8D=E9=BD=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit P3.4 加入 check_slo_compliance 後: - test_governance_agent::test_all_checks_fail_returns_all_errors: 4→5 - test_wave8_remaining_blockers::TestB8GovernanceFailureAlert: 三測試補 mock 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.7 (1M context) --- apps/api/tests/test_governance_agent.py | 19 +++++++++++-------- .../tests/test_wave8_remaining_blockers.py | 11 ++++++++--- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/apps/api/tests/test_governance_agent.py b/apps/api/tests/test_governance_agent.py index c9460f1b..edb59437 100644 --- a/apps/api/tests/test_governance_agent.py +++ b/apps/api/tests/test_governance_agent.py @@ -398,17 +398,19 @@ class TestRunSelfCheck: @pytest.mark.asyncio async def test_all_checks_fail_returns_all_errors(self): - """所有項目全部失敗 → 4 個 key 都有 error""" + """所有項目全部失敗 → 5 個 key 都有 error(2026-04-27 P3.4 加入 slo_compliance)""" agent = _make_agent() for attr in ["check_trust_drift", "check_knowledge_degradation", - "check_llm_hallucination", "check_execution_blast_radius"]: + "check_llm_hallucination", "check_execution_blast_radius", + "check_slo_compliance"]: setattr(agent, attr, AsyncMock(side_effect=Exception("mock failure"))) results = await agent.run_self_check() - assert len(results) == 4 - for key in ["trust_drift", "knowledge_degradation", "llm_hallucination", "execution_blast_radius"]: + assert len(results) == 5 + for key in ["trust_drift", "knowledge_degradation", "llm_hallucination", + "execution_blast_radius", "slo_compliance"]: assert "error" in results[key] @@ -514,13 +516,14 @@ class TestRunSelfCheckGlobalFailureAlert: @pytest.mark.asyncio async def test_all_four_checks_fail_triggers_alert_with_four_failed(self): - """4 項全失敗 → governance_self_failure 告警的 failed_checks 包含全部 4 個""" + """5 項全失敗 → governance_self_failure 告警的 failed_checks 包含全部 5 個(2026-04-27 P3.4 加 slo_compliance)""" alerter = AsyncMock() alerter.alert_governance = AsyncMock() agent = _make_agent(alerter=alerter) for attr in ["check_trust_drift", "check_knowledge_degradation", - "check_llm_hallucination", "check_execution_blast_radius"]: + "check_llm_hallucination", "check_execution_blast_radius", + "check_slo_compliance"]: setattr(agent, attr, AsyncMock(side_effect=Exception("all down"))) with patch("src.services.governance_agent.get_db_context") as mock_ctx: @@ -534,8 +537,8 @@ class TestRunSelfCheckGlobalFailureAlert: assert len(governance_failure_calls) >= 1 payload = governance_failure_calls[0][0][1] - assert payload["total_checks"] == 4 - assert len(payload["failed_checks"]) == 4 + assert payload["total_checks"] == 5 + assert len(payload["failed_checks"]) == 5 @pytest.mark.asyncio async def test_two_checks_fail_does_not_trigger_governance_self_failure(self): diff --git a/apps/api/tests/test_wave8_remaining_blockers.py b/apps/api/tests/test_wave8_remaining_blockers.py index cacb81e4..86e6ea5b 100644 --- a/apps/api/tests/test_wave8_remaining_blockers.py +++ b/apps/api/tests/test_wave8_remaining_blockers.py @@ -225,11 +225,12 @@ class TestB8GovernanceFailureAlert: from src.services.governance_agent import GovernanceAgent agent = GovernanceAgent() - # mock 四項 check:3 個 raise,1 個成功 + # 2026-04-27 P3.4: mock 五項 check(含 slo_compliance):3 raise,2 成功 agent.check_trust_drift = AsyncMock(side_effect=RuntimeError("DB down")) agent.check_knowledge_degradation = AsyncMock(side_effect=RuntimeError("KM error")) agent.check_llm_hallucination = AsyncMock(side_effect=RuntimeError("LLM error")) agent.check_execution_blast_radius = AsyncMock(return_value={"status": "ok"}) + agent.check_slo_compliance = AsyncMock(return_value={"status": "ok"}) agent._alert = AsyncMock() @@ -240,7 +241,7 @@ class TestB8GovernanceFailureAlert: call_args = agent._alert.await_args assert call_args[0][0] == "governance_self_failure" payload = call_args[0][1] - assert payload["total_checks"] == 4 + assert payload["total_checks"] == 5 assert len(payload["failed_checks"]) >= 3 @pytest.mark.asyncio @@ -249,10 +250,12 @@ class TestB8GovernanceFailureAlert: from src.services.governance_agent import GovernanceAgent agent = GovernanceAgent() + # 2026-04-27 P3.4: 加 slo_compliance(成功) agent.check_trust_drift = AsyncMock(side_effect=RuntimeError("err1")) agent.check_knowledge_degradation = AsyncMock(side_effect=RuntimeError("err2")) agent.check_llm_hallucination = AsyncMock(return_value={"status": "ok"}) agent.check_execution_blast_radius = AsyncMock(return_value={"status": "ok"}) + agent.check_slo_compliance = AsyncMock(return_value={"status": "ok"}) agent._alert = AsyncMock() @@ -267,10 +270,12 @@ class TestB8GovernanceFailureAlert: from src.services.governance_agent import GovernanceAgent agent = GovernanceAgent() + # 2026-04-27 P3.4: 5 項全失敗 agent.check_trust_drift = AsyncMock(side_effect=RuntimeError("e")) agent.check_knowledge_degradation = AsyncMock(side_effect=RuntimeError("e")) agent.check_llm_hallucination = AsyncMock(side_effect=RuntimeError("e")) agent.check_execution_blast_radius = AsyncMock(side_effect=RuntimeError("e")) + agent.check_slo_compliance = AsyncMock(side_effect=RuntimeError("e")) agent._alert = AsyncMock() @@ -278,4 +283,4 @@ class TestB8GovernanceFailureAlert: agent._alert.assert_awaited_once() payload = agent._alert.await_args[0][1] - assert len(payload["failed_checks"]) == 4 + assert len(payload["failed_checks"]) == 5