# @line_count 200 """测试规范选择器,实现规则+AI混合选择策略""" from typing import List, Dict, Any, Optional, TYPE_CHECKING from .test_standard_loader import TestStandardLoader import json import re if TYPE_CHECKING: from .api_client import APIClient class StandardSelector: """测试规范选择器,实现规则+AI混合选择策略""" def __init__(self, loader: TestStandardLoader, api_client: Optional['APIClient'] = None): """ 初始化规范选择器 Args: loader: 测试规范加载器 api_client: API客户端,用于AI辅助选择 """ self.loader = loader self.api_client = api_client self.mapping_rules = loader.get_requirement_mapping() self.keyword_mapping = loader.get_keyword_mapping() def select_standards(self, requirement: Dict[str, Any], use_ai: bool = True) -> List[str]: """ 为需求选择适用的测试规范 Args: requirement: 需求字典,包含requirement_type、description等 use_ai: 是否使用AI辅助选择(当规则匹配不足时) Returns: 测试规范ID列表 """ # 第一步:规则匹配 rule_based = self._rule_based_selection(requirement) # 第二步:如果规则匹配不足,使用AI补充 if use_ai and len(rule_based) < 2 and self.api_client: ai_based = self._ai_based_selection(requirement) # 合并去重 all_standards = list(set(rule_based + ai_based)) return all_standards return rule_based def _rule_based_selection(self, requirement: Dict[str, Any]) -> List[str]: """ 基于规则的规范选择 Args: requirement: 需求字典 Returns: 测试规范ID列表 """ standards = [] req_type = requirement.get('requirement_type', '') req_desc = requirement.get('description', '') # 1. 需求类型映射 if req_type in self.mapping_rules: mapping = self.mapping_rules[req_type] # 主要测试类型 standards.extend(mapping.get('primary', [])) # 次要测试类型 standards.extend(mapping.get('secondary', [])) # 条件性测试类型 conditionals = mapping.get('conditional', {}) if '有界面' in conditionals and ('界面' in req_desc or '显示' in req_desc): standards.extend(conditionals['有界面']) if '有性能要求' in conditionals and ('性能' in req_desc or '速度' in req_desc or '时间' in req_desc): standards.extend(conditionals['有性能要求']) if '安全关键' in conditionals and ('安全' in req_desc or '危险' in req_desc or '报警' in req_desc): standards.extend(conditionals['安全关键']) if '多软件交互' in conditionals and ('交互' in req_desc or '协同' in req_desc): standards.extend(conditionals['多软件交互']) if '性能相关' in conditionals and ('性能' in req_desc): standards.extend(conditionals['性能相关']) if '安全相关' in conditionals and ('安全' in req_desc): standards.extend(conditionals['安全相关']) # 2. 关键词匹配 for keyword, test_types in self.keyword_mapping.items(): if keyword in req_desc: standards.extend(test_types) # 3. 接口信息检测 if requirement.get('interface_info'): standards.append('外部接口测试') # 去重并返回 return list(set(standards)) def _ai_based_selection(self, requirement: Dict[str, Any]) -> List[str]: """ 基于AI的规范选择(当规则匹配不足时使用) Args: requirement: 需求字典 Returns: 测试规范ID列表 """ if not self.api_client: return [] # 获取所有测试规范名称 all_standards = self.loader.get_all_standards() standard_names = [f"{i+1}. {std.get('name', '')}" for i, std in enumerate(all_standards)] prompt = f"""根据以下需求,从14个测试类型中选择最适用的3-5个: {chr(10).join(standard_names)} 需求类型:{requirement.get('requirement_type', '未知')} 需求描述:{requirement.get('description', '')} 请只返回测试类型的名称列表,格式为JSON数组,例如:["功能测试", "性能测试", "边界测试"] 不要包含其他说明文字。""" try: response = self.api_client.call_api(prompt) # 尝试解析JSON test_types = self._parse_ai_response(response) return test_types except Exception as e: # 如果AI选择失败,返回空列表 print(f"AI选择失败: {str(e)}") return [] def _parse_ai_response(self, response: str) -> List[str]: """ 解析AI响应,提取测试类型列表 Args: response: AI响应文本 Returns: 测试类型名称列表 """ # 尝试直接解析JSON try: # 尝试提取JSON数组 json_match = re.search(r'\[.*?\]', response, re.DOTALL) if json_match: json_str = json_match.group(0) test_types = json.loads(json_str) if isinstance(test_types, list): return test_types except: pass # 如果JSON解析失败,尝试文本匹配 all_standards = self.loader.get_all_standards() standard_names = [std.get('name', '') for std in all_standards] found_types = [] for name in standard_names: if name in response: found_types.append(name) return found_types