Files
awoooi/apps/api/tests/test_golden_regression.py
Your Name 143c15f052
All checks were successful
CD Pipeline / build-and-deploy (push) Successful in 9m52s
feat(wave2+km): LLM 動態按鈕啟用 + KM 自動寫入 + AI Router dead code 標記
- ConfigMap: USE_LLM_DYNAMIC_BUTTONS=true(B2/B3/B4 handler 全就緒)
- decision_manager: auto_execute 失敗路徑補 KM fire-and-forget 寫入
- ai_router: _build_fallback_chain 標記 DEPRECATED 2026-04-28
- tests: test_golden_regression.py 新增 172 行 golden 回歸測試

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 15:27:33 +08:00

173 lines
6.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# apps/api/tests/test_golden_regression.py
# 2026-04-28 ogt + Claude Sonnet 4.6 — P3.2.4 黃金回歸測試集
"""
30 個黃金測試案例,保護 classify_alert_early() 邏輯不退步。
涵蓋 10 類告警場景。
函數簽章:
classify_alert_early(alertname, severity, labels=None, age_hours=0.0)
-> tuple[str, str] # (alert_category, notification_type)
"""
from __future__ import annotations
import pytest
from src.services.incident_service import classify_alert_early
class TestKubernetes:
def test_pod_crash_looping(self):
cat, ntype = classify_alert_early("PodCrashLooping", "critical")
assert cat == "kubernetes" and ntype == "TYPE-3"
def test_deploy_rollout_stuck(self):
cat, ntype = classify_alert_early("DeployRolloutStuck", "warning")
assert cat == "kubernetes" and ntype == "TYPE-3"
def test_kube_node_not_ready(self):
cat, ntype = classify_alert_early("KubeNodeNotReady", "critical")
assert cat == "kubernetes" and ntype == "TYPE-3"
def test_pod_oom_killed(self):
cat, ntype = classify_alert_early("PodOOMKilled", "warning")
assert cat == "kubernetes" and ntype == "TYPE-3"
def test_node_memory_pressure(self):
cat, ntype = classify_alert_early("NodeMemoryPressure", "warning")
assert cat == "kubernetes" and ntype == "TYPE-3"
class TestHostResource:
def test_host_high_cpu_load(self):
cat, ntype = classify_alert_early("HostHighCpuLoad", "critical")
assert cat == "host_resource" and ntype == "TYPE-3"
def test_host_high_memory(self):
cat, ntype = classify_alert_early("HostHighMemory", "warning")
assert cat == "host_resource" and ntype == "TYPE-3"
def test_host_disk_space_full(self):
cat, ntype = classify_alert_early("HostDiskSpaceFull", "critical")
assert cat == "host_resource" and ntype == "TYPE-3"
class TestHighCpuVariants:
"""HighCPU* prefix 規則覆蓋"""
def test_high_cpu_prefix(self):
cat, ntype = classify_alert_early("HighCPUUsage", "critical")
assert cat == "host_resource" and ntype == "TYPE-3"
def test_high_memory_prefix(self):
cat, ntype = classify_alert_early("HighMemoryPressure", "warning")
assert cat == "host_resource" and ntype == "TYPE-3"
class TestBackup:
def test_host_backup_failed_fresh(self):
"""< 24h 備份失敗 → TYPE-1pure info"""
cat, ntype = classify_alert_early("HostBackupFailed", "warning", age_hours=10.0)
assert cat == "backup" and ntype == "TYPE-1"
def test_host_backup_failed_stale_upgrade(self):
"""> 24h 備份失敗 → 升級為 TYPE-3P0 故障)"""
cat, ntype = classify_alert_early("HostBackupFailed", "warning", age_hours=25.0)
assert cat == "backup_failure" and ntype == "TYPE-3"
def test_host_backup_stale_upgrade(self):
cat, ntype = classify_alert_early("HostBackupStale", "warning", age_hours=30.0)
assert cat == "backup_failure" and ntype == "TYPE-3"
def test_backup_restore_test_not_upgraded(self):
"""BackupRestoreTestFailed 不受 age 升級影響"""
cat, ntype = classify_alert_early("BackupRestoreTestFailed", "warning", age_hours=48.0)
assert ntype == "TYPE-1"
class TestDatabase:
def test_postgres_connections_high(self):
cat, ntype = classify_alert_early("PostgreSQLConnectionsHigh", "warning")
assert cat == "database" and ntype == "TYPE-3"
def test_postgres_disk_growth_rate(self):
cat, ntype = classify_alert_early("PostgreSQLDiskGrowthRate", "warning")
assert cat == "database" and ntype == "TYPE-3"
def test_redis_memory_full(self):
cat, ntype = classify_alert_early("RedisMemoryFull", "critical")
assert cat == "database" and ntype == "TYPE-3"
class TestInfoAndHeartbeat:
def test_severity_info_is_type1(self):
_, ntype = classify_alert_early("SomeAlert", "info")
assert ntype == "TYPE-1"
def test_severity_none_is_type1(self):
_, ntype = classify_alert_early("SomeAlert", "none")
assert ntype == "TYPE-1"
def test_watchdog_heartbeat(self):
cat, ntype = classify_alert_early("Watchdog", "warning")
assert cat == "backup" and ntype == "TYPE-1"
def test_deadmansswitch(self):
cat, ntype = classify_alert_early("DeadMansSwitch", "critical")
assert cat == "backup" and ntype == "TYPE-1"
class TestConfigDrift:
def test_configuration_drift(self):
cat, ntype = classify_alert_early("ConfigurationDrift", "warning")
assert cat == "config_drift" and ntype == "TYPE-4D"
def test_kube_config_drift(self):
cat, ntype = classify_alert_early("KubeConfigDrift", "critical")
assert cat == "config_drift" and ntype == "TYPE-4D"
class TestFlywheelHealth:
def test_auto_repair_low_success(self):
cat, ntype = classify_alert_early("AutoRepairLowSuccessRate", "critical")
assert cat == "flywheel_health" and ntype == "TYPE-8M"
def test_ollama_down(self):
cat, ntype = classify_alert_early("OllamaDown", "critical")
assert cat == "flywheel_health" and ntype == "TYPE-8M"
class TestSecops:
def test_unauthorized_ssh(self):
cat, ntype = classify_alert_early("UnauthorizedSSH", "critical")
assert cat == "secops" and ntype == "TYPE-5S"
def test_pod_abnormal_activity(self):
cat, ntype = classify_alert_early("PodAbnormalActivity", "critical")
assert cat == "secops" and ntype == "TYPE-5S"
class TestDevopsAndExternal:
def test_gitea_down(self):
cat, ntype = classify_alert_early("GiteaDown", "critical")
assert cat == "devops_tool" and ntype == "TYPE-3"
def test_mowoo_work_down(self):
cat, ntype = classify_alert_early("MoWoooWorkDown", "critical")
assert cat == "external_site" and ntype == "TYPE-3"
def test_minio_down(self):
cat, ntype = classify_alert_early("MinIODown", "critical")
assert cat == "storage" and ntype == "TYPE-3"
class TestAlertChainAndGeneral:
def test_alert_chain_broken_alertmanager(self):
cat, ntype = classify_alert_early("AlertChainBroken_Alertmanager", "critical")
assert cat == "alertchain_health" and ntype == "TYPE-8M"
def test_no_alerts_received(self):
cat, ntype = classify_alert_early("NoAlertsReceived", "critical")
assert cat == "alertchain_health" and ntype == "TYPE-8M"
def test_unknown_alert_falls_to_general(self):
cat, ntype = classify_alert_early("SomeBrandNewUnknownAlert2026", "warning")
assert cat == "general" and ntype == "TYPE-3"