""" Smart Router Tests - Phase 13.3 =============================== 測試意圖分類、複雜度評分、AI 路由 """ from src.services.ai_router import ( AIRouter, get_ai_router, ) from src.services.complexity_scorer import ( ComplexityScorer, get_complexity_scorer, ) from src.services.intent_classifier import ( IntentClassifier, IntentType, get_intent_classifier, ) class TestIntentClassifier: """測試意圖分類器""" def test_alert_keywords(self): """測試告警關鍵字匹配""" classifier = IntentClassifier() # 中文告警 assert classifier.classify_sync("高負載警報") == IntentType.ALERT_TRIAGE assert classifier.classify_sync("CPU 異常告警") == IntentType.ALERT_TRIAGE assert classifier.classify_sync("OOM error detected") == IntentType.ALERT_TRIAGE def test_deployment_keywords(self): """測試部署關鍵字匹配""" classifier = IntentClassifier() assert classifier.classify_sync("部署新版本") == IntentType.DEPLOYMENT assert classifier.classify_sync("kubectl apply -f manifest.yaml") == IntentType.DEPLOYMENT assert classifier.classify_sync("rollout deployment api") == IntentType.DEPLOYMENT def test_query_keywords(self): """測試查詢關鍵字匹配""" classifier = IntentClassifier() assert classifier.classify_sync("查詢 Pod 狀態") == IntentType.QUERY assert classifier.classify_sync("kubectl get pods") == IntentType.QUERY assert classifier.classify_sync("現在有多少 replicas") == IntentType.QUERY def test_maintenance_keywords(self): """測試維運關鍵字匹配""" classifier = IntentClassifier() assert classifier.classify_sync("重啟服務") == IntentType.MAINTENANCE assert classifier.classify_sync("scale deployment to 5") == IntentType.MAINTENANCE assert classifier.classify_sync("回滾到上一版") == IntentType.MAINTENANCE def test_code_review_keywords(self): """測試程式碼審查關鍵字匹配""" classifier = IntentClassifier() assert classifier.classify_sync("review this PR") == IntentType.CODE_REVIEW assert classifier.classify_sync("審查這個 commit") == IntentType.CODE_REVIEW def test_unknown_intent(self): """測試未知意圖""" classifier = IntentClassifier() assert classifier.classify_sync("hello world") == IntentType.UNKNOWN assert classifier.classify_sync("今天天氣如何") == IntentType.UNKNOWN class TestComplexityScorer: """測試複雜度評分器""" def test_simple_context(self): """測試簡單上下文""" scorer = ComplexityScorer() result = scorer.score({}) assert result.score == 1 assert result.recommended_model == "llama3.2:3b" def test_multi_service_context(self): """測試多服務上下文""" scorer = ComplexityScorer() result = scorer.score({ "affected_services": ["api", "worker", "redis"], }) assert result.score >= 2 assert "service_count" in result.features def test_code_analysis_context(self): """測試需要程式碼分析""" scorer = ComplexityScorer() result = scorer.score({ "requires_code_analysis": True, }) assert result.score >= 2 assert result.features.get("code_analysis") == 1 def test_critical_severity(self): """測試 CRITICAL 嚴重程度""" scorer = ComplexityScorer() result = scorer.score({ "severity": "CRITICAL", }) assert result.score >= 2 assert result.features.get("severity") == 4 def test_complex_context(self): """測試複雜上下文""" scorer = ComplexityScorer() result = scorer.score({ "affected_services": ["api", "worker", "redis", "postgres"], "metrics": ["cpu", "memory", "latency", "error_rate", "rps"], "cross_system": True, "severity": "CRITICAL", }) assert result.score >= 4 # 複雜情況應該用雲端模型 assert result.recommended_model in ["gemini", "claude"] class TestAIRouter: """測試 AI 路由器""" def test_query_routes_to_fast_model(self): """測試查詢路由到快速模型""" router = AIRouter() decision = router.route_sync("查詢 Pod 狀態", {}) assert decision.model == "llama3.2:3b" assert decision.intent == IntentType.QUERY def test_code_review_routes_to_strong_model(self): """測試程式碼審查路由到強模型""" router = AIRouter() decision = router.route_sync("review this PR", {}) assert decision.model == "qwen2.5:7b-instruct" assert decision.intent == IntentType.CODE_REVIEW def test_complex_alert_routes_to_cloud(self): """測試複雜告警路由到雲端""" router = AIRouter() decision = router.route_sync("高負載告警", { "affected_services": ["api", "worker", "redis", "postgres"], "metrics": ["cpu", "memory", "latency", "error_rate"], "cross_system": True, "severity": "CRITICAL", }) assert decision.intent == IntentType.ALERT_TRIAGE assert decision.complexity.score >= 4 # 高複雜度告警應該用雲端 assert decision.model in ["gemini", "claude", "qwen2.5:7b-instruct"] def test_fallback_list(self): """測試 Fallback 列表""" router = AIRouter() decision = router.route_sync("查詢 Pod 狀態", {}) # Fallback 不應包含已選模型 assert decision.model not in decision.fallback_models # 應該有備援 assert len(decision.fallback_models) >= 2 class TestSingletons: """測試單例""" def test_intent_classifier_singleton(self): """測試 IntentClassifier 單例""" c1 = get_intent_classifier() c2 = get_intent_classifier() assert c1 is c2 def test_complexity_scorer_singleton(self): """測試 ComplexityScorer 單例""" s1 = get_complexity_scorer() s2 = get_complexity_scorer() assert s1 is s2 def test_ai_router_singleton(self): """測試 AIRouter 單例""" r1 = get_ai_router() r2 = get_ai_router() assert r1 is r2