Android Appium单测试后ADB连接失败、启动超时问题求助
嗨,我来帮你梳理下这个问题的核心和解决办法——我之前也碰到过类似UiAutomator2和noReset搭配的坑,咱们一步步来拆解:
你遇到的问题本质是**noReset=True配置和driver.reset()调用的冲突,导致Appium UiAutomator2依赖的Appium Settings应用状态异常**,进而让ADB的am start -W命令无法捕获应用启动完成的系统信号:
noReset=True是告诉Appium保留被测应用的缓存和用户数据,不要重置状态;- 但你调用了
driver.reset(),这个方法会强制清除被测应用数据并重启,两个操作本身就逻辑矛盾; - 更关键的是,UiAutomator2的核心服务依赖
Appium Settings应用,当这两个冲突操作触发后,Appium Settings的状态会和被测应用绑定混乱,导致后续ADB启动应用时,系统无法正常返回启动完成的回调,所以am start -W会一直挂起等待,最终触发超时。
另外还有个容易忽略的小细节:你的desired_capabilities里noReset用的是字符串'true',但Appium期望的是布尔值True,这个解析异常可能加剧了状态混乱的问题。
1. 先修复desired_capabilities的基础配置
把'noReset': 'true'改成布尔值True,同时调大ADB超时时间留足处理空间:
desired_capabilities = { 'platformName': 'Android', 'platformVersion': '8.0', 'deviceName': 'WVGA_API_26', 'avd': 'WVGA_API_26', 'app_package': 'com.ferly.ferly', 'app_activity': 'host.exp.exponent.experience.ShellAppActivity', 'app_wait_package': 'com.ferly.ferly', 'automationName': 'UiAutomator2', 'noReset': True, # 修正为布尔值 'adbExecTimeout': 30000 # 超时时间调整为30秒 }
2. 替换driver.reset()的实现,避免逻辑冲突
既然用了noReset=True,就不要用Appium自带的driver.reset(),而是用ADB命令手动重启应用,既保留应用数据,又能实现重启需求:
def restart_app(driver): app_package = driver.capabilities['appPackage'] app_activity = driver.capabilities['appActivity'] # 强制停止应用 driver.execute_script('mobile: shell', {'command': f'am force-stop {app_package}'}) # 启动应用(不用-W参数,避免等待超时) driver.execute_script('mobile: shell', {'command': f'am start -n {app_package}/{app_activity}'})
之后测试里需要重启应用的地方,调用这个方法即可。
3. 永久解决状态异常:清理Appium Settings状态
不用每次卸载Appium Settings,只需要清除它的缓存数据就能恢复状态,建议在测试结束后(不管成功失败)添加这个清理步骤:
def clean_appium_settings(driver): # 清除Appium Settings的缓存和数据 driver.execute_script('mobile: shell', {'command': 'pm clear io.appium.settings'})
如果担心初始化driver前状态异常,也可以提前用ADB命令检查并清理:
import subprocess def pre_check_device(device_id): # 检查Appium Settings是否存在 result = subprocess.run( f'adb -s {device_id} shell pm list packages io.appium.settings', capture_output=True, text=True ) if 'io.appium.settings' not in result.stdout: # Appium启动时会自动安装,这里无需手动操作 pass # 强制清除缓存 subprocess.run( f'adb -s {device_id} shell pm clear io.appium.settings', check=True )
4. 模拟器专属方案:用快照恢复状态
因为你用的是模拟器,可以创建一个干净的初始快照,每次测试前恢复快照,彻底避免状态积累的问题:
import subprocess def restore_emulator_snapshot(avd_name): # 关闭当前运行的模拟器 subprocess.run(f'adb -s emulator-5556 emu kill', capture_output=True) # 启动模拟器并恢复默认快照 subprocess.run(f'emulator -avd {avd_name} -no-boot-anim -snapshot default', check=True)
这个方法适合稳定的测试环境,每次测试都从干净状态开始,一劳永逸。
修改后先手动执行ADB命令测试:
adb -P 5037 -s emulator-5556 shell am start -W -n com.ferly.ferly/host.exp.exponent.experience.ShellAppActivity -S
如果能正常输出Complete,说明状态已经恢复,再跑Appium测试就不会超时了。
内容的提问来源于stack exchange,提问作者Surilan

