""" QA Agent - 测试工程师智能体 负责测试用例创建和 TDD 实践 """ from autogen import AssistantAgent from typing import Dict, Any, Optional import os from pathlib import Path from config.llm_config import get_agent_llm_config, QA_PROMPT class QAAgent: """测试工程师 Agent,负责生成测试用例和测试脚本""" def __init__(self, llm_config: Optional[Dict] = None): """ 初始化 QA Agent Args: llm_config: LLM 配置 """ self.llm_config = llm_config or get_agent_llm_config("QA_Agent") self.agent = AssistantAgent( name="QA_Agent", system_message=QA_PROMPT, llm_config=self.llm_config, description="资深测试工程师,专注于自动化测试和 TDD 实践", human_input_mode="NEVER" ) self.workspace_dir = Path("workspace") self.workspace_dir.mkdir(exist_ok=True) def generate_test_cases(self, srs_content: str) -> str: """ 根据 SRS 生成测试用例 Args: srs_content: SRS 文档内容 Returns: 生成的测试用例内容 """ prompt = f""" 请根据以下 SRS 文档生成完整的测试用例: {self._truncate(srs_content, 3000)} 请生成: 1. Pytest 测试脚本(包含完整的测试函数) 2. BDD 风格的测试场景描述 3. 测试数据准备 4. 预期结果验证 确保遵循 TDD 原则,测试先于代码存在。 """ response = self.agent.generate_reply( messages=[{"role": "user", "content": prompt}] ) test_content = response if isinstance(response, str) else str(response) # 保存测试文件 test_file = self.workspace_dir / "test_battery_health.py" with open(test_file, 'w', encoding='utf-8') as f: f.write(test_content) print(f"✅ 测试用例已生成:{test_file}") return test_content def create_bdd_scenarios(self, srs_content: str) -> str: """ 创建 BDD 风格的测试场景 Args: srs_content: SRS 文档内容 Returns: BDD 测试场景描述 """ prompt = f""" 请根据 SRS 创建 BDD (Behavior-Driven Development) 测试场景: {self._truncate(srs_content, 2000)} 请使用 Given-When-Then 格式描述每个测试场景: - Feature: 功能描述 - Scenario: 场景描述 - Given: 前置条件 - When: 操作 - Then: 预期结果 输出为 Markdown 格式。 """ response = self.agent.generate_reply( messages=[{"role": "user", "content": prompt}] ) bdd_content = response if isinstance(response, str) else str(response) # 保存 BDD 场景文件 bdd_file = self.workspace_dir / "bdd_scenarios.md" with open(bdd_file, 'w', encoding='utf-8') as f: f.write(bdd_content) print(f"✅ BDD 场景已生成:{bdd_file}") return bdd_content def analyze_test_coverage(self, test_code: str, srs_content: str) -> Dict[str, Any]: """ 分析测试覆盖率 Args: test_code: 测试代码 srs_content: SRS 文档 Returns: 覆盖率分析报告 """ prompt = f""" 请分析以下测试代码对 SRS 需求的覆盖情况: SRS 需求: {self._truncate(srs_content, 1500)} 测试代码: {self._truncate(test_code, 2000)} 请输出: 1. 已覆盖的需求列表 2. 未覆盖的需求列表 3. 覆盖率百分比 4. 改进建议 """ response = self.agent.generate_reply( messages=[{"role": "user", "content": prompt}] ) coverage_report = response if isinstance(response, str) else str(response) # 保存报告 report_file = self.workspace_dir / "coverage_report.md" with open(report_file, 'w', encoding='utf-8') as f: f.write(coverage_report) return {"report": coverage_report, "file": str(report_file)} def _truncate(self, text: str, max_length: int) -> str: """截断文本以避免超出上下文限制""" if len(text) <= max_length: return text return text[:max_length] + "... [内容已截断]" def run_tests(self, test_file_pattern: str = "test_*.py") -> Dict[str, Any]: """ 执行测试(需要实际运行 pytest) Args: test_file_pattern: 测试文件模式 Returns: 测试结果字典 """ import subprocess import sys try: # 使用 pytest 执行测试 result = subprocess.run( [sys.executable, "-m", "pytest", str(self.workspace_dir / test_file_pattern), "-v", "--tb=short"], capture_output=True, text=True, timeout=60 ) return { "success": result.returncode == 0, "stdout": result.stdout, "stderr": result.stderr, "returncode": result.returncode } except subprocess.TimeoutExpired: return { "success": False, "error": "测试执行超时" } except Exception as e: return { "success": False, "error": str(e) } def create_qa_agent(llm_config: Optional[Dict] = None) -> AssistantAgent: """ 创建 QA Agent(AutoGen 原生格式) Args: llm_config: LLM 配置 Returns: AutoGen AssistantAgent 实例 """ config = llm_config or get_agent_llm_config("QA_Agent") agent = AssistantAgent( name="QA_Agent", system_message=QA_PROMPT, llm_config=config, description="资深测试工程师", human_input_mode="NEVER" ) return agent