Files
test_item_gen/modules/standard_selector.py
2026-02-04 14:38:52 +08:00

168 lines
6.1 KiB
Python
Raw Permalink 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.
# @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