197 lines
6.8 KiB
Python
197 lines
6.8 KiB
Python
|
|
# @line_count 250
|
|||
|
|
"""测试规范管理器,整合规范加载、选择和Prompt构建"""
|
|||
|
|
from typing import List, Dict, Any, Optional, TYPE_CHECKING
|
|||
|
|
from .test_standard_loader import TestStandardLoader
|
|||
|
|
from .standard_selector import StandardSelector
|
|||
|
|
|
|||
|
|
if TYPE_CHECKING:
|
|||
|
|
from .api_client import APIClient
|
|||
|
|
|
|||
|
|
|
|||
|
|
class TestStandardManager:
|
|||
|
|
"""测试规范管理器,负责管理测试规范、选择适用规范、构建Prompt"""
|
|||
|
|
|
|||
|
|
def __init__(self, loader: Optional[TestStandardLoader] = None,
|
|||
|
|
selector: Optional[StandardSelector] = None,
|
|||
|
|
api_client: Optional['APIClient'] = None):
|
|||
|
|
"""
|
|||
|
|
初始化测试规范管理器
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
loader: 测试规范加载器,如果为None则创建新实例
|
|||
|
|
selector: 规范选择器,如果为None则创建新实例
|
|||
|
|
api_client: API客户端,用于AI辅助选择
|
|||
|
|
"""
|
|||
|
|
self.loader = loader or TestStandardLoader()
|
|||
|
|
self.api_client = api_client
|
|||
|
|
self.selector = selector or StandardSelector(self.loader, api_client)
|
|||
|
|
|
|||
|
|
def get_applicable_standards(self, requirement: Dict[str, Any],
|
|||
|
|
use_ai: bool = True) -> List[str]:
|
|||
|
|
"""
|
|||
|
|
为需求获取适用的测试规范
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
requirement: 需求字典
|
|||
|
|
use_ai: 是否使用AI辅助选择
|
|||
|
|
|
|||
|
|
Returns:
|
|||
|
|
测试规范ID列表
|
|||
|
|
"""
|
|||
|
|
return self.selector.select_standards(requirement, use_ai=use_ai)
|
|||
|
|
|
|||
|
|
def build_prompt(self, requirement: Dict[str, Any],
|
|||
|
|
standard_ids: Optional[List[str]] = None,
|
|||
|
|
include_full_content: bool = False) -> str:
|
|||
|
|
"""
|
|||
|
|
构建包含测试规范的分层Prompt
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
requirement: 需求字典
|
|||
|
|
standard_ids: 测试规范ID列表,如果为None则自动选择
|
|||
|
|
include_full_content: 是否包含完整规范内容(默认只包含摘要)
|
|||
|
|
|
|||
|
|
Returns:
|
|||
|
|
格式化后的Prompt文本
|
|||
|
|
"""
|
|||
|
|
# 如果没有指定规范,自动选择
|
|||
|
|
if standard_ids is None:
|
|||
|
|
standard_ids = self.get_applicable_standards(requirement)
|
|||
|
|
|
|||
|
|
# Level 1: 测试规范摘要
|
|||
|
|
standards_summary = self._build_standards_summary(standard_ids, include_full_content)
|
|||
|
|
|
|||
|
|
# Level 2: 需求信息
|
|||
|
|
requirement_info = self._format_requirement(requirement)
|
|||
|
|
|
|||
|
|
# 构建完整Prompt
|
|||
|
|
prompt = f"""你是一位资深的软件测试专家,请严格按照以下测试规范生成测试用例。
|
|||
|
|
|
|||
|
|
【适用的测试规范】
|
|||
|
|
根据需求类型"{requirement.get('requirement_type', '未知')}",以下测试规范适用:
|
|||
|
|
|
|||
|
|
{standards_summary}
|
|||
|
|
|
|||
|
|
【需求信息】
|
|||
|
|
{requirement_info}
|
|||
|
|
|
|||
|
|
【生成要求】
|
|||
|
|
1. 必须覆盖上述测试规范中的所有关键测试点
|
|||
|
|
2. 每个适用的测试规范至少生成1个测试项
|
|||
|
|
3. 测试用例要详细、可执行,包含:
|
|||
|
|
- 前置条件
|
|||
|
|
- 详细测试步骤(编号清晰)
|
|||
|
|
- 预期结果
|
|||
|
|
- 优先级(高/中/低)
|
|||
|
|
4. 确保覆盖正常功能、异常情况、边界条件
|
|||
|
|
5. 每个测试项应标注引用的测试规范(standard_reference字段)
|
|||
|
|
|
|||
|
|
【输出格式】
|
|||
|
|
以JSON格式输出,格式如下:
|
|||
|
|
{{
|
|||
|
|
"test_items": [
|
|||
|
|
{{
|
|||
|
|
"name": "测试项名称",
|
|||
|
|
"test_type": "功能测试",
|
|||
|
|
"priority": "高",
|
|||
|
|
"test_objective": "测试目标",
|
|||
|
|
"standard_reference": "功能测试",
|
|||
|
|
"test_cases": [
|
|||
|
|
{{
|
|||
|
|
"name": "测试用例名称",
|
|||
|
|
"preconditions": "前置条件",
|
|||
|
|
"test_steps": ["步骤1", "步骤2", "步骤3"],
|
|||
|
|
"expected_result": "预期结果",
|
|||
|
|
"priority": "高",
|
|||
|
|
"test_type": "功能测试"
|
|||
|
|
}}
|
|||
|
|
]
|
|||
|
|
}}
|
|||
|
|
]
|
|||
|
|
}}"""
|
|||
|
|
|
|||
|
|
return prompt
|
|||
|
|
|
|||
|
|
def _build_standards_summary(self, standard_ids: List[str],
|
|||
|
|
include_full: bool = False) -> str:
|
|||
|
|
"""
|
|||
|
|
构建测试规范摘要
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
standard_ids: 测试规范ID列表
|
|||
|
|
include_full: 是否包含完整内容
|
|||
|
|
|
|||
|
|
Returns:
|
|||
|
|
格式化后的规范摘要
|
|||
|
|
"""
|
|||
|
|
if not standard_ids:
|
|||
|
|
return "无适用的测试规范"
|
|||
|
|
|
|||
|
|
return self.loader.format_standards_summary(standard_ids)
|
|||
|
|
|
|||
|
|
def _format_requirement(self, requirement: Dict[str, Any]) -> str:
|
|||
|
|
"""
|
|||
|
|
格式化需求信息
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
requirement: 需求字典
|
|||
|
|
|
|||
|
|
Returns:
|
|||
|
|
格式化后的需求信息文本
|
|||
|
|
"""
|
|||
|
|
lines = []
|
|||
|
|
lines.append(f"需求编号:{requirement.get('requirement_id', 'N/A')}")
|
|||
|
|
lines.append(f"需求类型:{requirement.get('requirement_type', 'N/A')}")
|
|||
|
|
lines.append(f"需求描述:{requirement.get('description', 'N/A')}")
|
|||
|
|
|
|||
|
|
module_name = requirement.get('module_name', '')
|
|||
|
|
if module_name:
|
|||
|
|
lines.append(f"所属模块:{module_name}")
|
|||
|
|
|
|||
|
|
# 接口信息(如果有)
|
|||
|
|
interface_info = requirement.get('interface_info')
|
|||
|
|
if interface_info:
|
|||
|
|
lines.append("\n【接口信息】")
|
|||
|
|
if interface_info.get('接口名称'):
|
|||
|
|
lines.append(f"接口名称:{interface_info['接口名称']}")
|
|||
|
|
if interface_info.get('接口类型'):
|
|||
|
|
lines.append(f"接口类型:{interface_info['接口类型']}")
|
|||
|
|
if interface_info.get('来源'):
|
|||
|
|
lines.append(f"来源:{interface_info['来源']}")
|
|||
|
|
if interface_info.get('目的地'):
|
|||
|
|
lines.append(f"目的地:{interface_info['目的地']}")
|
|||
|
|
|
|||
|
|
return "\n".join(lines)
|
|||
|
|
|
|||
|
|
def get_standards_summary(self, standard_ids: List[str]) -> str:
|
|||
|
|
"""
|
|||
|
|
获取测试规范摘要(便捷方法)
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
standard_ids: 测试规范ID列表
|
|||
|
|
|
|||
|
|
Returns:
|
|||
|
|
规范摘要文本
|
|||
|
|
"""
|
|||
|
|
return self.loader.format_standards_summary(standard_ids)
|
|||
|
|
|
|||
|
|
def confirm_test_types(self, requirement: Dict[str, Any],
|
|||
|
|
candidate_standards: List[str]) -> List[str]:
|
|||
|
|
"""
|
|||
|
|
确认最终使用的测试类型(两阶段生成策略的阶段1)
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
requirement: 需求字典
|
|||
|
|
candidate_standards: 候选测试规范ID列表
|
|||
|
|
|
|||
|
|
Returns:
|
|||
|
|
确认后的测试规范ID列表
|
|||
|
|
"""
|
|||
|
|
# 如果候选类型不多(<=3),直接使用
|
|||
|
|
if len(candidate_standards) <= 3:
|
|||
|
|
return candidate_standards
|
|||
|
|
|
|||
|
|
# 如果候选类型较多,可以进一步筛选
|
|||
|
|
# 这里简化处理,直接返回前5个
|
|||
|
|
return candidate_standards[:5]
|