#!/usr/bin/env python3 """ test_agent.py - 场景测试脚本 通过指定 scene,直接调用 GuiAgentBridge 在 Android 设备上执行完整场景测试。 脚本会复用 scene_configs.json、GuiAgentBridge 和当前 FSM 运行时逻辑, 因此适合验证 login/register 等场景化 prompt 是否按预期工作。 用法:直接修改下方 CONFIG 字典中的配置,然后运行 python3 test_agent.py """ import os import sys import logging from pathlib import Path # ============================================================================== # 配置区 - 所有参数在这里修改,无需命令行参数 # ============================================================================== CONFIG = { "scene": "login", # 要测试的场景名,如 login/register/payment "additional_info": "", # 可选:补充本次测试目标,会追加到 scene prompt 后 "device_serial": None, # ADB 设备序列号,None = 自动选择第一个设备 "is_emulator": True, # 是否模拟器 "max_steps": None, # 可选:覆盖 scene 配置中的 total_steps;None 表示使用配置值 "max_error_steps": 15, # 最大连续失败步数 "output_dir": "./test_agent_output", # 截图等输出目录 "app_name": None, # 可选:用于日志与 prompt 展示的 app 名称 } # ============================================================================== # 环境初始化 # ============================================================================== ROOT = Path(__file__).resolve().parent if str(ROOT) not in sys.path: sys.path.insert(0, str(ROOT)) logging.basicConfig( level=logging.INFO, format="%(asctime)s [%(name)-12s] %(levelname)-7s %(message)s", datefmt="%H:%M:%S", ) logger = logging.getLogger("TestAgent") # 导入项目模块 —— 触发平台自动注册 from DroidBot.core import PlatformFactory from DroidBot import platforms # noqa: F401 - 触发 Android 平台注册 from DroidBot.guiagent_bridge import GuiAgentBridge from DroidBot.guiagent_core.scene_config_loader import load_scene_config def validate_scene(scene: str, platform: str = "android") -> dict: """校验 scene 是否存在,并返回对应配置。""" scene_config = load_scene_config(platform) scenes = scene_config.get("scenes", {}) if scene not in scenes: available = ", ".join(sorted(scenes.keys())) raise ValueError(f"未知场景 '{scene}',当前 {platform} 可用场景: {available}") return scenes[scene] def run_agent(config: dict): """初始化设备并执行指定 scene。""" scene = config.get("scene") if not scene: raise ValueError("CONFIG['scene'] 必填") additional_info = config.get("additional_info") or config.get("prompt") or "" max_steps = config.get("max_steps") max_error_steps = config.get("max_error_steps", 15) output_dir = config.get("output_dir", "./test_agent_output") os.makedirs(output_dir, exist_ok=True) logger.info("=" * 60) logger.info("校验场景配置...") scene_spec = validate_scene(scene, platform="android") logger.info( "场景有效: scene=%s, initial_stage=%s, stages=%s", scene, scene_spec.get("initial_stage", "main"), list(scene_spec.get("stages", {}).keys()), ) logger.info("=" * 60) logger.info("初始化 Android 设备...") device = PlatformFactory.create_device( "android", device_serial=config.get("device_serial"), is_emulator=config.get("is_emulator", True), output_dir=output_dir, ) try: device.set_up() device.connect() logger.info("设备连接成功") display_info = device.get_display_info() width = display_info.get("width", 1080) height = display_info.get("height", 1920) logger.info(f"设备分辨率: {(width, height)}") logger.info("初始化 GuiAgentBridge...") bridge = GuiAgentBridge( device=device, app_name=config.get("app_name"), ) logger.info("GuiAgentBridge 初始化成功") current_state = device.get_current_state() context = {"state": current_state} if additional_info: context["additional_info"] = additional_info logger.info(f"附加信息: {additional_info}") logger.info("=" * 60) logger.info( "开始执行场景测试: scene=%s, max_steps=%s, max_error_steps=%s", scene, max_steps if max_steps is not None else "scene_config", max_error_steps, ) success, message, reason_code = bridge.handle_with_guiagent( category=scene, context=context, max_steps=max_steps, max_error_steps=max_error_steps, ) logger.info("=" * 60) logger.info("场景执行完成") logger.info("success=%s", success) logger.info("message=%s", message) logger.info("reason_code=%s", reason_code) logger.info("=" * 60) except KeyboardInterrupt: logger.warning("用户手动中断") except Exception as e: logger.error(f"执行异常: {e}") import traceback traceback.print_exc() finally: logger.info("断开设备连接...") try: device.disconnect() except Exception as e: logger.warning(f"断开设备时发生异常: {e}") logger.info("设备已断开") if __name__ == "__main__": run_agent(CONFIG)