""" Mumu模拟器 pytest 测试框架 """ import pytest import pyautogui import time import os import subprocess import requests from pathlib import Path # 配置 MUMU_EXE_PATH = r"C:\Program Files\Netease\MuMu\nx_main\MuMuNxMain.exe" MUMU_PROCESS_NAME = "MuMuNxMain.exe" ADB_PATH = r"C:\Program Files\Netease\MuMu\shell\adb.exe" APK_DOWNLOAD_URL = "http://your-server.com/app-release.apk" LOCAL_APK_PATH = os.path.join(os.path.dirname(__file__), "test_app.apk") INSTALLED_PACKAGE_NAME = "com.example.flomo_ai" WEB_URL = "http://192.168.3.15/" SCRIPT_DIR = os.path.dirname(__file__) class MumuEmulator: """Mumu模拟器控制类""" def __init__(self): self.process_name = MUMU_PROCESS_NAME self.script_dir = SCRIPT_DIR pyautogui.PAUSE = 1 pyautogui.FAILSAFE = True def is_running(self) -> bool: """检查模拟器是否运行""" try: result = subprocess.run( ["tasklist"], capture_output=True, text=True ) return self.process_name in result.stdout except Exception: return False def start(self): """启动模拟器""" if not self.is_running(): subprocess.Popen(MUMU_EXE_PATH) time.sleep(5) def find_and_click(self, image_name, confidence=0.8, timeout=30): """查找图片并点击""" image_path = os.path.join(self.script_dir, f"{image_name}.png") if not os.path.exists(image_path): print(f"图片不存在: {image_path}") return False start_time = time.time() while time.time() - start_time < timeout: try: location = pyautogui.locateOnScreen(image_path, confidence=confidence) if location: center = pyautogui.center(location) pyautogui.click(center) print(f"点击了: {image_name}") return True except Exception as e: pass time.sleep(1) print(f"未找到图片: {image_name}") return False def type_text(self, text): """输入文本""" pyautogui.write(text, interval=0.1) print(f"输入了文本: {text}") def press_enter(self): """按回车""" pyautogui.press("enter") print("按下回车") def wait_for_boot(self, timeout=120): """等待模拟器启动完成""" boot_completed = False start_time = time.time() while time.time() - start_time < timeout: if self.is_running(): time.sleep(5) boot_completed = True break time.sleep(2) return boot_completed def check_image_exists(self, image_name, confidence=0.8) -> bool: """检查图片是否存在""" image_path = os.path.join(self.script_dir, f"{image_name}.png") if not os.path.exists(image_path): return False try: location = pyautogui.locateOnScreen(image_path, confidence=confidence) return location is not None except Exception: return False def run_sequence(self): """按顺序执行任务""" sequence = [ "start", "running", "web", "web.address", "web_goon", "web_debug", "web_debug_apk", "web_debug_apk_download", "web_debug_apk_open", "web_debug_apk_install", "web_debug_apk_run" ] for image_name in sequence: if image_name == "web.address": if self.check_image_exists("web.address"): time.sleep(1) self.type_text(WEB_URL) time.sleep(0.5) self.press_enter() else: print("web.address 图片不存在,跳过输入URL") else: self.find_and_click(image_name, timeout=10) time.sleep(2) def close(self): """关闭模拟器""" try: subprocess.run(["taskkill", "/F", "/IM", self.process_name]) except Exception: pass class AdbHelper: """ADB命令辅助类""" def __init__(self): self.adb_path = ADB_PATH def exec_cmd(self, *args): """执行ADB命令""" cmd = [self.adb_path] + list(args) result = subprocess.run(cmd, capture_output=True, text=True) return result.stdout, result.stderr def install_apk(self, apk_path: str) -> bool: """安装APK""" stdout, stderr = self.exec_cmd("install", "-r", apk_path) return "Success" in stdout def uninstall_app(self, package_name: str) -> bool: """卸载应用""" stdout, stderr = self.exec_cmd("uninstall", package_name) return "Success" in stdout def launch_app(self, package_name: str, activity: str): """启动应用""" self.exec_cmd("shell", "am", "start", "-n", f"{package_name}/{activity}") def is_app_installed(self, package_name: str) -> bool: """检查应用是否已安装""" stdout, _ = self.exec_cmd("shell", "pm", "list", "packages", package_name) return package_name in stdout def pull_file(self, remote_path: str, local_path: str): """从模拟器拉取文件""" self.exec_cmd("pull", remote_path, local_path) @pytest.fixture(scope="session") def emulator(): """模拟器fixture""" mumu = MumuEmulator() yield mumu # 测试结束后清理 if mumu.is_running(): mumu.close() @pytest.fixture(scope="session") def adb(): """ADB fixture""" return AdbHelper() @pytest.fixture(scope="session") def download_apk(): """下载APK""" if os.path.exists(LOCAL_APK_PATH): return LOCAL_APK_PATH response = requests.get(APK_DOWNLOAD_URL, stream=True) with open(LOCAL_APK_PATH, "wb") as f: for chunk in response.iter_content(chunk_size=8192): f.write(chunk) yield LOCAL_APK_PATH # 清理 if os.path.exists(LOCAL_APK_PATH): os.remove(LOCAL_APK_PATH)