更新mumu-pytest测试框架,修复build.gradle.kts依赖问题
This commit is contained in:
@@ -9,20 +9,42 @@ android {
|
||||
|
||||
defaultConfig {
|
||||
applicationId = "com.example.flomo_ai"
|
||||
minSdk = 28
|
||||
//noinspection OldTargetApi
|
||||
minSdk = 24
|
||||
targetSdk = 34
|
||||
versionCode = 1
|
||||
versionName = "1.1"
|
||||
versionCode = 2
|
||||
versionName = "1.2"
|
||||
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
vectorDrawables {
|
||||
useSupportLibrary = true
|
||||
}
|
||||
|
||||
// 启用 View Binding
|
||||
buildFeatures {
|
||||
viewBinding = true
|
||||
}
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
getByName("main") {
|
||||
java.srcDirs("src/main/java")
|
||||
res.srcDirs("src/main/res")
|
||||
manifest.srcFile("src/main/AndroidManifest.xml")
|
||||
}
|
||||
getByName("test") {
|
||||
java.srcDirs("src/test/java")
|
||||
}
|
||||
getByName("androidTest") {
|
||||
java.srcDirs("src/androidTest/java")
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
debug {
|
||||
isDebuggable = true
|
||||
isMinifyEnabled = false
|
||||
applicationIdSuffix = ".debug"
|
||||
}
|
||||
release {
|
||||
isMinifyEnabled = false
|
||||
proguardFiles(
|
||||
@@ -63,6 +85,30 @@ dependencies {
|
||||
implementation(libs.androidx.material3)
|
||||
implementation(libs.appcompat)
|
||||
implementation(libs.material)
|
||||
|
||||
// 网络请求相关
|
||||
implementation(libs.okhttp)
|
||||
implementation(libs.logging.interceptor)
|
||||
|
||||
// JSON解析
|
||||
implementation(libs.gson)
|
||||
implementation(libs.moshi.kotlin)
|
||||
|
||||
// 协程支持
|
||||
implementation(libs.kotlinx.coroutines.core)
|
||||
implementation(libs.kotlinx.coroutines.android)
|
||||
|
||||
// JWT处理
|
||||
implementation(libs.kjwt.jwks)
|
||||
implementation(libs.nimbus.jose.jwt)
|
||||
|
||||
// 权限处理 (已移除PermissionX,代码中未使用)
|
||||
|
||||
// 图片加载
|
||||
implementation("com.github.bumptech.glide:glide:4.16.0")
|
||||
annotationProcessor("com.github.bumptech.glide:compiler:4.16.0")
|
||||
|
||||
// 测试依赖
|
||||
testImplementation(libs.junit)
|
||||
androidTestImplementation(libs.androidx.junit)
|
||||
androidTestImplementation(libs.androidx.espresso.core)
|
||||
@@ -70,13 +116,4 @@ dependencies {
|
||||
androidTestImplementation(libs.androidx.ui.test.junit4)
|
||||
debugImplementation(libs.androidx.ui.tooling)
|
||||
debugImplementation(libs.androidx.ui.test.manifest)
|
||||
implementation(libs.gson)
|
||||
implementation(libs.kjwt.jwks)
|
||||
implementation(libs.nimbus.jose.jwt)
|
||||
implementation(libs.okhttp)
|
||||
implementation(libs.logging.interceptor)
|
||||
implementation(libs.kotlinx.coroutines.core)
|
||||
implementation(libs.kotlinx.coroutines.android)
|
||||
implementation(libs.moshi.kotlin)
|
||||
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
||||
@@ -1,6 +1,6 @@
|
||||
[versions]
|
||||
agp = "8.6.0"
|
||||
gradle = "7.0.4"
|
||||
agp = "8.13.2"
|
||||
gradle = "8.13.2"
|
||||
gson = "2.10.1"
|
||||
kjwtJwks = "0.9.0"
|
||||
kotlin = "1.9.0"
|
||||
@@ -8,7 +8,7 @@ coreKtx = "1.10.1"
|
||||
junit = "4.13.2"
|
||||
junitVersion = "1.1.5"
|
||||
espressoCore = "3.5.1"
|
||||
kotlinGradlePlugin = "1.6.10"
|
||||
kotlinGradlePlugin = "1.6.21"
|
||||
kotlinxCoroutinesAndroid = "1.7.1"
|
||||
kotlinxCoroutinesCore = "1.7.1"
|
||||
lifecycleRuntimeKtx = "2.6.1"
|
||||
@@ -21,6 +21,7 @@ material = "1.12.0"
|
||||
moshiKotlin = "1.12.0"
|
||||
nimbusJoseJwt = "9.40"
|
||||
okhttp = "4.12.0"
|
||||
permissionx = "1.7.1"
|
||||
|
||||
[libraries]
|
||||
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
|
||||
@@ -50,6 +51,7 @@ material = { group = "com.google.android.material", name = "material", version.r
|
||||
moshi-kotlin = { module = "com.squareup.moshi:moshi-kotlin", version.ref = "moshiKotlin" }
|
||||
nimbus-jose-jwt = { module = "com.nimbusds:nimbus-jose-jwt", version.ref = "nimbusJoseJwt" }
|
||||
okhttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp" }
|
||||
permissionx = { group = "com.permissionx.guolindev", name = "permissionx", version.ref = "permissionx" }
|
||||
|
||||
[plugins]
|
||||
android-application = { id = "com.android.application", version.ref = "agp" }
|
||||
|
||||
@@ -33,28 +33,54 @@ pip install -r requirements.txt
|
||||
|
||||
```python
|
||||
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"
|
||||
WEB_URL = "http://192.168.3.15/"
|
||||
INSTALLED_PACKAGE_NAME = "com.example.flomo_ai"
|
||||
APK_DOWNLOAD_URL = "http://your-server.com/app-release.apk"
|
||||
```
|
||||
|
||||
## 图片说明
|
||||
## 功能说明
|
||||
|
||||
将以下图片放入 `mumu-pytest` 目录:
|
||||
### MumuEmulator 类
|
||||
|
||||
| 文件名 | 说明 |
|
||||
|--------|------|
|
||||
| start.png | 启动按钮 |
|
||||
| running.png | 运行中标识 |
|
||||
| web.png | Web按钮 |
|
||||
| web_address.png | 地址输入框 |
|
||||
| web_goon.png | 继续按钮 |
|
||||
| web_debug.png | 调试按钮 |
|
||||
| web_debug_apk.png | APK按钮 |
|
||||
| web_debug_apk_download.png | 下载按钮 |
|
||||
| web_debug_apk_open.png | 打开文件按钮 |
|
||||
| web_debug_apk_install.png | 安装按钮 |
|
||||
| web_debug_apk_run.png | 运行按钮 |
|
||||
| 方法 | 说明 |
|
||||
|------|------|
|
||||
| `is_running()` | 检查模拟器是否运行 |
|
||||
| `start()` | 启动模拟器并置顶窗口 |
|
||||
| `bring_to_front()` | 将模拟器窗口置顶 |
|
||||
| `find_and_click(image_name, confidence, timeout)` | 查找图片并点击 |
|
||||
| `type_text(text)` | 输入文本 |
|
||||
| `press_enter()` | 按回车 |
|
||||
| `wait_for_boot(timeout)` | 等待模拟器启动完成 |
|
||||
| `check_image_exists(image_name)` | 检查图片是否存在 |
|
||||
| `run_sequence()` | 按顺序执行任务 |
|
||||
| `close()` | 关闭模拟器 |
|
||||
|
||||
### AdbHelper 类
|
||||
|
||||
| 方法 | 说明 |
|
||||
|------|------|
|
||||
| `exec_cmd(*args)` | 执行ADB命令 |
|
||||
| `install_apk(apk_path)` | 安装APK |
|
||||
| `uninstall_app(package_name)` | 卸载应用 |
|
||||
| `launch_app(package_name, activity)` | 启动应用 |
|
||||
| `is_app_installed(package_name)` | 检查应用是否已安装 |
|
||||
| `pull_file(remote_path, local_path)` | 从模拟器拉取文件 |
|
||||
|
||||
## 测试流程 (run_sequence)
|
||||
|
||||
1. 置顶模拟器窗口
|
||||
2. 等待30秒
|
||||
3. 点击 web.png
|
||||
4. 检测 web_address.png 出现后,输入 URL (http://192.168.3.15/)
|
||||
5. 点击 web_goon.png
|
||||
6. 点击 web_debug.png
|
||||
7. 点击 web_debug_apk.png
|
||||
8. 点击 web_debug_apk_download.png
|
||||
9. 点击 web_debug_apk_open.png
|
||||
10. 点击 web_debug_apk_install.png
|
||||
11. 点击 web_debug_apk_run.png
|
||||
|
||||
## 运行测试
|
||||
|
||||
@@ -62,27 +88,18 @@ INSTALLED_PACKAGE_NAME = "com.example.flomo_ai"
|
||||
# 运行所有测试
|
||||
pytest
|
||||
|
||||
# 运行指定测试
|
||||
pytest test_mumu.py::test_start_emulator_sequence
|
||||
pytest test_mumu.py::test_run_sequence
|
||||
|
||||
# 显示详细输出
|
||||
pytest -v -s
|
||||
```
|
||||
|
||||
## 测试流程
|
||||
|
||||
1. 启动模拟器 (start.png)
|
||||
2. 等待运行中 (running.png)
|
||||
3. 点击Web按钮 (web.png)
|
||||
4. 输入URL地址 (web_address.png -> http://192.168.3.15/)
|
||||
5. 点击继续 (web_goon.png)
|
||||
6. 点击调试 (web_debug.png)
|
||||
7. 点击APK (web_debug_apk.png)
|
||||
8. 点击下载 (web_debug_apk_download.png)
|
||||
9. 点击打开 (web_debug_apk_open.png)
|
||||
10. 点击安装 (web_debug_apk_install.png)
|
||||
11. 点击运行 (web_debug_apk_run.png)
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. 确保MuMu模拟器已正确安装
|
||||
2. 需要先截取各个步骤对应的图片
|
||||
3. pyautogui需要配置合适的置信度和超时时间
|
||||
2. 需要先截取各个步骤对应的图片放入 mumu-pytest 目录
|
||||
3. pyautogui需要配置合适的置信度(默认0.8)和超时时间
|
||||
4. 确保模拟器路径和ADB路径正确
|
||||
5. 测试图片文件名不要包含空格,使用下划线分隔
|
||||
|
||||
@@ -4,6 +4,7 @@ Mumu模拟器 pytest 测试框架
|
||||
|
||||
import pytest
|
||||
import pyautogui
|
||||
import pygetwindow as gw
|
||||
import time
|
||||
import os
|
||||
import subprocess
|
||||
@@ -48,6 +49,24 @@ class MumuEmulator:
|
||||
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):
|
||||
"""查找图片并点击"""
|
||||
@@ -106,11 +125,11 @@ class MumuEmulator:
|
||||
|
||||
def run_sequence(self):
|
||||
"""按顺序执行任务"""
|
||||
self.bring_to_front()
|
||||
time.sleep(30)
|
||||
sequence = [
|
||||
"start",
|
||||
"running",
|
||||
"web",
|
||||
"web.address",
|
||||
"web_address",
|
||||
"web_goon",
|
||||
"web_debug",
|
||||
"web_debug_apk",
|
||||
@@ -121,16 +140,19 @@ class MumuEmulator:
|
||||
]
|
||||
|
||||
for image_name in sequence:
|
||||
if image_name == "web.address":
|
||||
if self.check_image_exists("web.address"):
|
||||
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)
|
||||
self.type_text(WEB_URL)
|
||||
time.sleep(0.5)
|
||||
self.press_enter()
|
||||
else:
|
||||
print("web.address 图片不存在,跳过输入URL")
|
||||
print("web_address 图片不存在,跳过输入URL")
|
||||
else:
|
||||
self.find_and_click(image_name, timeout=10)
|
||||
self.find_and_click(image_name, timeout=60)
|
||||
time.sleep(2)
|
||||
|
||||
def close(self):
|
||||
|
||||
@@ -3,17 +3,48 @@ Mumu模拟器测试
|
||||
"""
|
||||
|
||||
import pytest
|
||||
import pyautogui
|
||||
import os
|
||||
import time
|
||||
|
||||
|
||||
def test_start_emulator_sequence(emulator):
|
||||
"""测试模拟器启动和操作序列"""
|
||||
assert not emulator.is_running(), "模拟器已启动"
|
||||
time.sleep(3)
|
||||
emulator.start()
|
||||
time.sleep(3)
|
||||
|
||||
script_dir = os.path.dirname(__file__)
|
||||
start_image_path = os.path.join(script_dir, "start.png")
|
||||
|
||||
if not os.path.exists(start_image_path):
|
||||
pytest.fail(f"start.png 图片文件不存在: {start_image_path}")
|
||||
|
||||
print("正在查找 start.png 图片...")
|
||||
location = None
|
||||
for _ in range(10):
|
||||
try:
|
||||
location = pyautogui.locateOnScreen(start_image_path, confidence=0.8)
|
||||
if location:
|
||||
break
|
||||
except Exception:
|
||||
pass
|
||||
time.sleep(1)
|
||||
|
||||
if not location:
|
||||
print("未找到 start.png,退出 pytest")
|
||||
pytest.exit("未在屏幕上找到 start.png 图片,测试终止")
|
||||
|
||||
center = pyautogui.center(location)
|
||||
pyautogui.click(center)
|
||||
print(f"已点击 start.png,位置: {center}")
|
||||
|
||||
assert emulator.is_running(), "模拟器启动失败"
|
||||
|
||||
|
||||
def test_run_sequence(emulator):
|
||||
"""测试按顺序执行任务"""
|
||||
time.sleep(3)
|
||||
if not emulator.is_running():
|
||||
pytest.skip("模拟器未运行")
|
||||
|
||||
@@ -22,6 +53,7 @@ def test_run_sequence(emulator):
|
||||
|
||||
def test_close_emulator(emulator):
|
||||
"""测试关闭模拟器"""
|
||||
time.sleep(3)
|
||||
if emulator.is_running():
|
||||
emulator.close()
|
||||
assert not emulator.is_running(), "模拟器关闭失败"
|
||||
|
||||
Reference in New Issue
Block a user