Files
flomo-ai/mumu-pytest/conftest.py

234 lines
7.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
Mumu模拟器 pytest 测试框架
"""
import pytest
import pyautogui
import pygetwindow as gw
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)
self.bring_to_front()
def bring_to_front(self):
"""将模拟器窗口置顶"""
try:
windows = gw.getWindowsWithTitle("MuMu")
for window in windows:
if window.title:
window.activate()
window.restore()
time.sleep(0.5)
print(f"已将窗口置顶: {window.title}")
return True
print("未找到MuMu模拟器窗口")
return False
except Exception as e:
print(f"置顶窗口失败: {e}")
return False
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):
"""按顺序执行任务"""
self.bring_to_front()
time.sleep(30)
sequence = [
"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":
for _ in range(60):
if self.check_image_exists("web_address"):
time.sleep(1)
self.type_text(WEB_URL)
time.sleep(0.5)
self.press_enter()
break
time.sleep(1)
else:
print("web_address 图片不存在跳过输入URL")
else:
self.find_and_click(image_name, timeout=60)
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)