#!/usr/bin/env python3 """ AceFlow v2.0 第1阶段验收测试脚本 全面测试核心功能和用户体验 """ import os import sys import json import yaml import subprocess import time from pathlib import Path from datetime import datetime class AceFlowAcceptanceTest: def __init__(self): self.project_root = Path.cwd() self.aceflow_dir = self.project_root / ".aceflow" self.test_results = [] self.total_tests = 0 self.passed_tests = 0 def log_test(self, test_name, passed, message=""): """记录测试结果""" self.total_tests += 1 if passed: self.passed_tests += 1 status = "✅ PASS" else: status = "❌ FAIL" result = f"{status} {test_name}" if message: result += f" - {message}" self.test_results.append(result) print(result) return passed def run_command(self, command, expect_success=True): """运行命令并返回结果""" try: result = subprocess.run( command, shell=True, capture_output=True, text=True, cwd=self.project_root ) if expect_success: return result.returncode == 0, result.stdout, result.stderr else: return result.returncode != 0, result.stdout, result.stderr except Exception as e: return False, "", str(e) def test_directory_structure(self): """测试目录结构完整性""" print("\n🗂️ 测试目录结构...") required_dirs = [ ".aceflow", ".aceflow/scripts", ".aceflow/config", ".aceflow/templates", ".aceflow/web", ".aceflow/state", ".aceflow/templates/minimal", ".aceflow/templates/standard" ] for dir_path in required_dirs: path = self.project_root / dir_path self.log_test( f"目录存在: {dir_path}", path.exists() and path.is_dir() ) def test_core_files(self): """测试核心文件存在性""" print("\n📄 测试核心文件...") required_files = [ ".aceflow/scripts/aceflow", ".aceflow/scripts/wizard.py", ".aceflow/config.yaml", ".aceflow/state/project_state.json", ".aceflow/config/flow_modes.yaml", ".aceflow/config/agile_integration.yaml", ".aceflow/web/index.html", ".aceflow/templates/minimal/template.yaml", ".aceflow/templates/minimal/requirements.md", ".aceflow/templates/minimal/tasks.md", ".aceflow/templates/standard/template.yaml", ".clineignore", ".clinerules/quality_rules.yaml" ] for file_path in required_files: path = self.project_root / file_path self.log_test( f"文件存在: {file_path}", path.exists() and path.is_file() ) def test_file_permissions(self): """测试文件权限""" print("\n🔐 测试文件权限...") executable_files = [ ".aceflow/scripts/aceflow", ".aceflow/scripts/wizard.py" ] for file_path in executable_files: path = self.project_root / file_path if path.exists(): is_executable = os.access(path, os.X_OK) self.log_test( f"可执行权限: {file_path}", is_executable ) def test_config_files(self): """测试配置文件格式""" print("\n⚙️ 测试配置文件...") # 测试主配置文件 config_file = self.aceflow_dir / "config.yaml" try: with open(config_file, 'r', encoding='utf-8') as f: config = yaml.safe_load(f) # 检查必需的配置项 required_keys = ['project', 'flow', 'agile', 'ai', 'web'] all_keys_present = all(key in config for key in required_keys) self.log_test( "主配置文件格式正确", all_keys_present, f"包含所需配置项: {required_keys}" ) except Exception as e: self.log_test( "主配置文件格式正确", False, f"解析错误: {e}" ) # 测试状态文件 state_file = self.aceflow_dir / "state" / "project_state.json" try: with open(state_file, 'r', encoding='utf-8') as f: state = json.load(f) required_keys = ['project_id', 'flow_mode', 'current_stage', 'stage_states'] all_keys_present = all(key in state for key in required_keys) self.log_test( "状态文件格式正确", all_keys_present, f"包含所需状态项: {required_keys}" ) except Exception as e: self.log_test( "状态文件格式正确", False, f"解析错误: {e}" ) def test_cli_commands(self): """测试CLI命令功能""" print("\n🖥️ 测试CLI命令...") # 测试help命令 success, stdout, stderr = self.run_command("python3 .aceflow/scripts/aceflow help") self.log_test( "help命令正常", success and "AceFlow v2.0" in stdout ) # 测试status命令 success, stdout, stderr = self.run_command("python3 .aceflow/scripts/aceflow status") self.log_test( "status命令正常", success and "项目状态" in stdout ) # 测试start命令(如果还没有活跃阶段) success, stdout, stderr = self.run_command("python3 .aceflow/scripts/aceflow start") if "已开始阶段" in stdout or "当前已有活跃阶段" in stdout: self.log_test("start命令正常", True) else: self.log_test("start命令正常", success) # 测试progress命令 success, stdout, stderr = self.run_command("python3 .aceflow/scripts/aceflow progress --progress 50") if "进度更新" in stdout or "没有活跃的阶段" in stdout: self.log_test("progress命令正常", True) else: self.log_test("progress命令正常", success) # 测试web命令 success, stdout, stderr = self.run_command("python3 .aceflow/scripts/aceflow web") self.log_test( "web命令正常", success and ("Web界面已打开" in stdout or "index.html" in stdout) ) def test_flow_modes(self): """测试流程模式配置""" print("\n🔄 测试流程模式...") flow_config_file = self.aceflow_dir / "config" / "flow_modes.yaml" try: with open(flow_config_file, 'r', encoding='utf-8') as f: flow_config = yaml.safe_load(f) # 检查三种模式是否都存在 required_modes = ['minimal', 'standard', 'complete'] modes_exist = all(mode in flow_config['flow_modes'] for mode in required_modes) self.log_test( "流程模式配置完整", modes_exist, f"包含模式: {required_modes}" ) # 检查轻量级模式的阶段配置 minimal_mode = flow_config['flow_modes']['minimal'] minimal_stages = minimal_mode.get('stages', {}) expected_stages = ['P', 'D', 'R'] stages_correct = all(stage in minimal_stages for stage in expected_stages) self.log_test( "轻量级模式阶段正确", stages_correct, f"包含阶段: {expected_stages}" ) except Exception as e: self.log_test( "流程模式配置完整", False, f"配置错误: {e}" ) def test_templates(self): """测试项目模板""" print("\n📋 测试项目模板...") # 测试轻量级模板 minimal_template = self.aceflow_dir / "templates" / "minimal" / "template.yaml" try: with open(minimal_template, 'r', encoding='utf-8') as f: template = yaml.safe_load(f) has_project_config = 'project' in template has_flow_config = 'flow' in template has_init_config = 'initialization' in template self.log_test( "轻量级模板配置正确", has_project_config and has_flow_config and has_init_config ) except Exception as e: self.log_test( "轻量级模板配置正确", False, f"模板错误: {e}" ) # 测试模板文档文件 template_docs = [ ".aceflow/templates/minimal/requirements.md", ".aceflow/templates/minimal/tasks.md" ] for doc_file in template_docs: path = self.project_root / doc_file content_exists = False if path.exists(): with open(path, 'r', encoding='utf-8') as f: content = f.read() content_exists = len(content.strip()) > 0 self.log_test( f"模板文档: {Path(doc_file).name}", content_exists ) def test_web_interface(self): """测试Web界面""" print("\n🌐 测试Web界面...") web_file = self.aceflow_dir / "web" / "index.html" if web_file.exists(): with open(web_file, 'r', encoding='utf-8') as f: content = f.read() # 检查关键HTML元素 has_title = "AceFlow" in content has_styles = "