从零构建安卓自动化测试:Python+Appium+MuMu模拟器全流程指南
每次手动测试App时,你是否也厌倦了那些重复的点击、滑动和验证?作为一名曾经的"手工测试劳工",我完全理解这种痛苦。直到发现Python+Appium这套自动化组合拳,才真正从机械劳动中解放出来。本文将带你完整走通环境搭建到脚本编写的全流程,特别针对Windows平台下使用网易MuMu模拟器的各种"坑"给出解决方案。
1. 环境准备:搭建自动化测试基石
自动化测试的环境配置就像盖房子的地基,一步错可能导致后续满盘皆输。我们需要准备的软件清单如下:
- Java开发工具包(JDK):Appium基于Java开发,必须安装JDK 8或以上版本
- Android SDK:包含adb等关键工具,建议下载Android Studio后通过SDK Manager安装
- Python 3.7+:我们的脚本语言环境,推荐使用最新稳定版
- Appium Desktop:可视化服务端工具,比命令行版本更友好
- Node.js:Appium的运行时环境
- 网易MuMu模拟器:轻量级安卓模拟器,对电脑配置要求较低
安装完成后,需要配置几个关键环境变量:
| 变量名 | 值示例 | 作用说明 |
|---|---|---|
| JAVA_HOME | C:\Program Files\Java\jdk | 指定JDK安装位置 |
| ANDROID_HOME | C:\Android\Sdk | 指向Android SDK目录 |
| Path | %JAVA_HOME%\bin | 添加Java和adb到系统路径 |
提示:验证环境变量是否生效,可以在命令行分别执行
java -version、adb version和python --version查看输出。
2. MuMu模拟器特殊配置:解决adb连接难题
MuMu模拟器使用自定义的adb端口和二进制文件,这导致直接使用Android SDK的adb会连接失败。以下是必须执行的调整步骤:
- 定位MuMu安装目录下的adb.exe(通常在
\emulator\nemu\vmonitor\bin) - 复制该文件替换Android SDK的adb(
platform-tools目录下) - 重启命令行窗口使更改生效
连接模拟器的关键命令序列:
adb kill-server # 终止现有adb服务 adb connect 127.0.0.1:7555 # MuMu默认监听端口 adb devices # 应显示已连接设备常见问题排查:
- 端口占用:执行
netstat -ano | findstr "5037"查找占用进程 - 连接超时:检查模拟器是否开启USB调试模式(设置→关于手机→连续点击版本号激活开发者选项)
3. Appium服务配置:搭建桥梁
Appium作为中间层,负责将Python脚本指令转化为模拟器可执行操作。推荐使用Appium Desktop进行可视化配置:
- 启动Appium Server GUI
- 保持默认主机(127.0.0.1)和端口(4723)
- 在"Edit Configurations"中设置:
ANDROID_HOME:你的SDK路径JAVA_HOME:JDK安装路径
- 保存后启动服务
验证服务是否正常:
- 访问
http://localhost:4723/wd/hub/status应返回JSON格式的状态信息 - 出现"Could not connect to server"错误时,检查Node.js版本是否兼容
4. 编写首个自动化脚本:从点击到断言
下面是一个完整的Python测试脚本模板,实现了基础操作链:
from appium import webdriver from appium.webdriver.common.touch_action import TouchAction import time desired_caps = { 'platformName': 'Android', 'deviceName': 'MuMu', # 任意命名 'platformVersion': '6.0.1', # 需与模拟器版本一致 'appPackage': 'com.example.app', # 待测App包名 'appActivity': '.MainActivity', # 启动Activity 'automationName': 'UIAutomator2', 'noReset': True # 避免每次重置App } driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps) # 元素定位与操作 login_btn = driver.find_element_by_id('com.example.app:id/login') login_btn.click() # 输入文本 username = driver.find_element_by_xpath('//android.widget.EditText[@text="用户名"]') username.send_keys('testuser') # 滑动操作 TouchAction(driver).press(x=500, y=1500).move_to(x=500, y=500).release().perform() # 验证Toast消息 toast = driver.find_element_by_xpath('//*[contains(@text, "登录成功")]') assert toast.is_displayed() driver.quit()获取App包名和Activity的两种方法:
- 使用aapt工具:
aapt dump badging app.apk | findstr package - 运行App后执行:
adb shell dumpsys window | findstr mCurrentFocus
5. 高级技巧与优化策略
当基础脚本运行稳定后,可以考虑以下进阶方案:
页面对象模式(POM)将元素定位与业务逻辑分离,创建可复用的页面类:
class LoginPage: def __init__(self, driver): self.driver = driver @property def username_field(self): return self.driver.find_element_by_id('com.example.app:id/username') def login(self, username, password): self.username_field.send_keys(username) # 其他登录步骤...并行测试配置在desired capabilities中指定不同设备参数,配合pytest-xdist实现并行执行:
def pytest_generate_tests(metafunc): if 'device' in metafunc.fixturenames: metafunc.parametrize('device', [ {'port': 4723, 'udid': 'emulator-5554'}, {'port': 4724, 'udid': 'emulator-5556'} ])异常处理机制增加智能等待和自动重试逻辑:
from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC try: element = WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.ID, "dynamicElement")) ) except TimeoutException: driver.save_screenshot('timeout_error.png') raise6. 持续集成:让测试自动运行
将自动化测试接入CI/CD流水线,实现每次代码提交后的自动验证。以Jenkins为例的配置要点:
- 安装Python插件和Android环境插件
- 创建自由风格项目,添加构建步骤:
pip install -r requirements.txt pytest tests/ --html=report.html - 添加HTML报告发布配置
- 设置定时构建或Git钩子触发
关键优化指标监控:
- 用例通过率
- 平均执行时长
- 元素定位稳定性
- 异常截图留存率
遇到元素定位失败时,不要立即认为脚本有问题。先手动打开App,使用Appium Inspector或UI Automator Viewer确认元素属性是否变更。有时候简单的XPath调整就能解决问题,比如将//Button[@text="登录"]改为//*[contains(@text, "登")]提高容错性。