简介
前面课程只是启动了单个 appium 服务, 只能控制单台设备. 如果需要针对多台设备测试那么该如何处理? 而且发现群里的小伙伴们也在时不时地在讨论这个问题, 想知道怎么实现的, 于是宏哥就决定写一片这样的文章来给小伙伴们, 答答疑, 解解惑. 希望对各位小伙伴或者童鞋们有所帮助, 可以是你们豁然开朗.
启动多个 appium 服务
首先看下面两个启动 appium 服务案例.
启动 appium 服务 1
启动 appium 服务 2
上面案例我们启动了 2 个不同的 appium 服务器, 他们通过不同的端口来区分不同的服务; 如同百米赛跑要给不同的运动员安排不同的赛道, 每个运动员也只能在自己指定的赛道进行比赛.
1. 启动 appium 服务, 可以用命令行模式
比如
第一个 appium 服务, 可以指定一个端口 -p 4723, 然后指定一个设备名称 -u [AVD 模拟器] , 也就是 - U 参数 (adb devices 可以查看),-bp 是指定 Bootstrap-port
- (多个 appium 启动链接多个 Android 设备时需要设置不同的 Bootstrap-port )
- appium -a 127.0.0.1 -p 4723 -bp 4726 -U ML5RRPCUWO
第二个 appium 服务指定设备名称 [夜神模拟器]
appium -a 127.0.0.1 -p 4724 -bp 4725 -U 127.0.0.1:62001
Appium 常用参数
参数 | 默认值 | 含义 |
-U, --udid | null | 连接物理设备的唯一设备标识符 |
-a, --address | 0.0.0.0 | 监听的 ip 地址 |
-p, --port | 4723 | 监听的端口 |
-bp, --bootstrap-port | 4724 | 连接 Android 设备的端口号 (Android-only) |
-g, --log | null | 将日志输出到指定文件 |
--no-reset | false | session 之间不重置应用状态 |
--session-override | false | 允许 session 被覆盖 (冲突的话) |
--app-activity | null | 打开 Android 应用时,启动的 Activity(Android-only) 的名字 |
--app | null | 本地绝对路径_或_远程 http URL 所指向的一个安装包 |
更多参数请输入命令: appium -h
Appium 安卓手机每次运行时都要安装 Unlock,Setting 解决方案
首先通过如下命令找到 appium 的安装路径
where appium
1. 打开 C:\Users\Shuqing\AppData\Roaming\NPM\node_modules\appium\node_modules\appium-Android-driver\lib 中的 Android-helpers.JS
- # 注释 475 行如下代码
- //await helpers.pushSettingsApp(adb);
- # 注释 486 行如下代码
- //await helpers.pushUnlock(adb);
2. 打开 C:\Users\Shuqing\AppData\Roaming\NPM\node_modules\appium\node_modules\appium-Android-driver\build\lib 中的 Android-helpers.JS
- # 注释 1128 行下面这行代码
- //return _regeneratorRuntime.awrap(helpers.pushSettingsApp(adb));
- # 修改为如下:
- return context$1$0.abrupt('return', defaultIME);
- # 注释 1163 行下面这行代码
- //return _regeneratorRuntime.awrap(helpers.pushUnlock(adb));
- # 修改如下:
- return context$1$0.abrupt('return', defaultIME);
修改完成后重启 Appium 服务即可, 如果新设备没有这个两个守护 App 可以手动安装这两个 App 到设备.
Appium Setting 路径 :
{appium 安装路径}\node_modules\_io.appium.settings@2.4.0@io.appium.settings\App\build\outputs\apk\settings_apk-debug.apk
- eg:
- C:\Users\Shuqing\AppData\Roaming\NPM\node_modules\appium\node_modules\_io.appium.settings@2.4.0@io.appium.settings\App\build\outputs\apk\settings_apk-debug.apk
Unlock App 路径:
appium 安装路径 \ node_modules\_appium-unlock@2.0.0@appium-unlock\bin \unlock_apk-debug.apk
- eg:
- C:\Users\Shuqing\AppData\Roaming\NPM\node_modules\appium\node_modules\_io.appium.settings@2.4.0@io.appium.settings\App\build\outputs\apk\unlock_apk-debug.apk
多设备启动
前面我们已经启动了多个 appium 服务, 那么接下来我们可以基于这些服务来启动不同的设备.
测试场景
连接以下 2 台设备, 然后分别启动考研帮 App
设备 1:127.0.0.1:62001(夜神模拟器)
设备 2:emulator-5554(AVD 模拟器)
代码实现
desired_caps.YAML
- platformName: Android
- platformVersion: 5.1.1
- deviceName: 127.0.0.1:62001
- App: C:\Users\DELL\Downloads\kaoyanbang.apk
- appPackage: com.tal.kaoyan
- appActivity: com.tal.kaoyan.ui.activity.SplashActivity
- noReset: False
- unicodeKeyboard: True
- resetKeyboard: True
- ip: 127.0.0.1
multi_device.py
- # coding=utf-8
- # 1. 先设置编码, utf-8 可支持中英文, 如上, 一般放在第一行
- # 2. 注释: 包括记录创建时间, 创建人, 项目名称.
- '''
- Created on 2019-9-14
- @author: 北京 - 宏哥 QQ 交流群: 707699217
- Project: 学习和使用 appium 自动化测试 - 并发测试
- '''
- # 3. 导入模块
- from appium import webdriver
- import YAML
- from time import ctime
- with open('desired_caps.yaml', 'r')as file:
- data = YAML.load(file)
- devices_list = ['127.0.0.1:62001', 'emulator-5554']
- def appium_desire(udid, port):
- desired_caps = {}
- desired_caps['platformName'] = data['platformName']
- desired_caps['platformVersion'] = data['platformVersion']
- desired_caps['deviceName'] = data['deviceName']
- desired_caps['udid'] = udid
- desired_caps['app'] = data['app']
- desired_caps['appPackage'] = data['appPackage']
- desired_caps['appActivity'] = data['appActivity']
- desired_caps['noReset'] = data['noReset']
- print('appium port: %s start run %s at %s' % (port, udid, ctime()))
- driver = webdriver.Remote('http://' + str(data['ip']) + ':' + str(port) + '/wd/hub', desired_caps)
- return driver
- if __name__ == '__main__':
- appium_desire(devices_list[0], 4723)
- appium_desire(devices_list[1], 4725)
代码运行结果
设备运行结果
夜神模拟器
AVD 模拟器
多进程并发启动设备
上面的案例设备启动并不是并发进行的, 而是先后执行. 那个设备在前边就先执行那个, 那么如何实现 2 台设备同时启动, 并启动 App 呢?
测试场景
同时启动 2 台设备:'emulator-5554'和'127.0.0.1:62001'并打开考研帮 App
实现思路
可以使用 Python 多线程或者多进程实现. 这里我们推荐使用多进程 ( multiprocessing) 原因如下:
多进程中, 同一个变量, 各自有一份拷贝存在于每个进程中, 互不影响.
而多线程中, 所有变量都由所有线程共享, 所以, 任何一个变量都可以被任何一个线程修改, 因此, 线程之间共享数据最大的危险在于多个线程同时改一个变量, 容易把内容给改乱了.
有兴趣的小伙伴或者童鞋们可以看一下以下的知识点:
线程与进程
Python 多进程
python 多线程
代码实现
multi_devices_sync.py
- # coding=utf-8
- # 1. 先设置编码, utf-8 可支持中英文, 如上, 一般放在第一行
- # 2. 注释: 包括记录创建时间, 创建人, 项目名称.
- '''
- Created on 2019-9-14
- @author: 北京 - 宏哥 QQ 交流群: 707699217
- Project: 学习和使用 appium 自动化测试 - 并发测试
- '''
- # 3. 导入模块
- from appium import webdriver
- import YAML
- from time import ctime
- import multiprocessing
- with open('desired_caps.yaml', 'r') as file:
- data = YAML.load(file)
- devices_list = ['127.0.0.1:62001', '127.0.0.1:62025']
- def appium_desired(udid, port):
- desired_caps = {}
- desired_caps['platformName'] = data['platformName']
- desired_caps['platformVersion'] = data['platformVersion']
- desired_caps['deviceName'] = data['deviceName']
- desired_caps['udid'] = udid
- desired_caps['app'] = data['app']
- desired_caps['appPackage'] = data['appPackage']
- desired_caps['appActivity'] = data['appActivity']
- desired_caps['noReset'] = data['noReset']
- print('appium port:%s start run %s at %s' % (port, udid, ctime()))
- driver = webdriver.Remote('http://' + str(data['ip']) + ':' + str(port) + '/wd/hub', desired_caps)
- driver.implicitly_wait(5)
- return driver
- # 构建 desired 进程租
- desired_process = []
- # 加载 desied 进程
- for i in range(len(devices_list)):
- port = 4723 + 2 * i
- desired = multiprocessing.Process(target=appium_desired, args=(devices_list[i], port))
- desired_process.append(desired)
- if __name__ == '__main__':
- # 启动多设备执行测试
- for desired in desired_process:
- desired.start()
- for desired in desired_process:
- desired.join()
小结
Appium 服务通过命令行 appium 启动报错 error: uncaughtException: Cannot find module 'internal/util/types'
这个错误困扰了宏哥很久, 不是找不到解决办法, 而是宏哥在犹豫要不要试一下下边的所说的解决办法呢??? 因为前边的 appium 的环境都搭建好了, 如果卸载了, 安装了低版本的 node, 会不会引发一系列的其他环境不兼容的让人头疼的问题, 等等的考虑吧! 最后刚好碰到中秋节, 时间充裕, 宏哥痛定思痛的还是下定决心卸载试一下, 毕竟活着就是不断地折腾的呗! 最后宏哥试了一下是否可以安装一个高版本和低版本的 node 在一个系统中, 你如果需要高版本的切换高版本的 node, 如果需要低版本的切换低版本的 node, 这样这个问题就会完美解决了, 有兴趣的可以看一下宏哥的这篇文章: 手把手告诉你如何安装多个版本的 node(非常详细, 非常实用).
解决方法:
是因为版本不匹配. 我装的 appium 版本是 1.4.16, 而 node 版本是 v10.16.0, 把 node 卸载了, 装 v6.9.4, 完美解决~
node 版本是 v10.16.0
appium 版本是 1.4.16
v6.9.4 下载: v6.9.4 地址 https://nodejs.org/dist/v6.9.4/
您的肯定就是我进步的动力. 如果你感觉还不错, 就请鼓励一下吧! 记得点波推荐 哦!!!(点击右边的小球即可!(^__^) 嘻嘻......)
来源: https://www.cnblogs.com/du-hong/p/11411953.html