python+appium 自动化测试-Appium 并发测试之多设备启动
Posted 酔清风
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python+appium 自动化测试-Appium 并发测试之多设备启动相关的知识,希望对你有一定的参考价值。
一、启动 appium 服务器(文末有福利哦)
1.通过命令行窗口启动单个 appium 服务器
appium -- 直接打开默认的4723端口号
appium -p 4723 -- 使用-p来启动固定端口号的appium服务器
2.通过命令行窗口启动多个 appium 服务器
appium -p 4723
appium -p 4726
二、启动多个设备
1.在 yaml 文件配置 Capability 参数
desired_caps.yaml
platformName: android
platformVersion: '9'
deviceName: U4AIUKFAL7W4MJLR
appPackage: com.sina.weibo
appActivity: com.sina.weibo.SplashActivity
automationName: UiAutomator2
autoGrantPermissions: True
noReset: True
url: 127.0.0.1
注意:
- 手机系统版本号属于字符串格式,需要加''引号
- url 为 appium 服务器的地址
- 启动多个设备需要启动多个 appium 服务,所以这边不设置端口号
2.代码实现
from time import ctime
import yaml
from appium import webdriver
devices_list = ['U4AIUKFAL7W4MJLR', 'U4AIUKFAL7W4MHUHUDS']
with open(r"E:\\\\study\\\\Fork\\\\WeiboDemo\\\\Weibo\\\\config\\\\desired_caps.yaml", 'r') as file:
data = yaml.load(file, Loader=yaml.FullLoader)
def multi_app_start(udid, port):
desired_caps = 'platformName': data['platformName'],
'platformVersion': data['platformVersion'],
'deviceName': data['deviceName'],
'udid': udid,
'appPackage': data['appPackage'],
'appActivity': data['appActivity'],
'automationName': data['automationName'],
'autoGrantPermissions': data['autoGrantPermissions'],
'noReset': data['noReset']
print('appium port:%s start run %s at %s' % (port, udid, ctime()))
driver = webdriver.Remote('http://' + str(data['url']) + ':' + str(port) + '/wd/hub', desired_caps)
driver.implicitly_wait(10)
return driver
# 测试函数,在实际运行过程中可以注释
if __name__ == '__main__':
multi_app_start(devices_list[0], 4723)
multi_app_start(devices_list[1], 4725)
注意:
- 需要开启两个 appium 服务,且端口号不能一样
- 连接的设备主要根据 udid 连接,而不是根据 yaml 文件中的 deviceName,所以在 yaml 文件中的 deviceName 可以随意设置
- ctime() 表示当前时间
- 以上为成功启动一个后才会启动另外一个,不是同步启动两个设备
最后运行结果为:
对以上代码封装成类:
class MultiDevices:
driver: webdriver = None
devices_list = ['U4AIUKFAL7W4MJLR', 'U4AIUKFAL7W4MHUHUDS']
def appium_desire(self, udid, port):
with open(r"E:\\study\\Fork\\WeiboDemo\\Weibo\\config\\desired_caps.yaml", 'r') as file:
data = yaml.load(file, Loader=yaml.FullLoader)
desired_caps = 'platformName': data['platformName'],
'platformVersion': data['platformVersion'],
'deviceName': data['deviceName'],
'udid': udid,
'appPackage': data['appPackage'],
'appActivity': data['appActivity'],
'automationName': data['automationName'],
'autoGrantPermissions': data['autoGrantPermissions'],
'noReset': data['noReset']
print('appium port:%s start run %s at %s' % (port, udid, ctime()))
self.driver = webdriver.Remote('http://' + str(data['url']) + ':' + str(port) + '/wd/hub', desired_caps)
self.driver.implicitly_wait(10)
return self.driver
# 测试函数,在实际运行中可以注释
if __name__ == '__main__':
mas1 = MultiDevices()
mas2 = MultiDevices()
mas1.appium_desire(MultiDevices.devices_list[0], 4723)
mas2.appium_desire(MultiDevices.devices_list[1], 4725)
三、多进程并发启动设备
- 多进程中,同一个变量,各自有拷贝一份存在于每个进程中,互不影响
- 多线程中,所有变量都由所有线程共享,任意一个比那辆都可以被任何一个线程修改,因此,线程之间共享数据最大的危险在于多个线程同时改一个变量,容易把内容改乱了
所以我使用的是多进程并发启动设备
yaml 文件同上,代码实现如下:
import multiprocessing
from time import ctime
import yaml
from appium import webdriver
devices_list = ['U4AIUKFAL7W4MJLR', 'U4AIUKFAL7W4MHUHUDS']
with open(r"E:\\\\study\\\\Fork\\\\WeiboDemo\\\\Weibo\\\\config\\\\desired_caps.yaml", 'r') as file:
data = yaml.load(file, Loader=yaml.FullLoader)
def multi_app_start(udid, port):
desired_caps = 'platformName': data['platformName'],
'platformVersion': data['platformVersion'],
'deviceName': data['deviceName'],
'udid': udid,
'appPackage': data['appPackage'],
'appActivity': data['appActivity'],
'automationName': data['automationName'],
'autoGrantPermissions': data['autoGrantPermissions'],
'noReset': data['noReset']
print('appium port:%s start run %s at %s' % (port, udid, ctime()))
driver = webdriver.Remote('http://' + str(data['url']) + ':' + str(port) + '/wd/hub', desired_caps)
driver.implicitly_wait(10)
return driver
# 构建desired进程组
desired_process = []
# 加载desired进程
for i in range(len(devices_list)):
port = 4723 + 2 * i
# target="调用的方法",args="传入的参数"
desired = multiprocessing.Process(target=multi_app_start, 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()
结果同上,但同时启动,控制台输出的日志中时间一致
对以上代码封装成类
class MultiDevicesSync:
driver: webdriver = None
devices_list = ['U4AIUKFAL7W4MJLR', 'U4AIUKFAL7W4MHUHUDS']
def multi_devices_sync(udid, port):
with open(r"E:\\study\\Fork\\WeiboDemo\\Weibo\\config\\desired_caps.yaml", 'r') as file:
data = yaml.load(file, Loader=yaml.FullLoader)
desired_caps = 'platformName': data['platformName'],
'platformVersion': data['platformVersion'],
'deviceName': data['deviceName'],
'udid': udid,
'appPackage': data['appPackage'],
'appActivity': data['appActivity'],
'automationName': data['automationName'],
'autoGrantPermissions': data['autoGrantPermissions'],
'noReset': data['noReset']
print('appium port:%s start run %s at %s' % (port, udid, ctime()))
driver = webdriver.Remote('http://' + str(data['url']) + ':' + str(port) + '/wd/hub', desired_caps)
driver.implicitly_wait(10)
return driver
# 构建desired进程组
desired_process = []
# 加载desired进程
for i in range(len(devices_list)):
port = 4723 + 2 * i
# target="调用的方法",args="传入的参数"
desired = multiprocessing.Process(target=multi_devices_sync, args=(devices_list[i], port))
desired_process.append(desired)
if __name__ == '__main__':
multi_devices_sync = MultiDevicesSync()
# 启动多设备执行测试
for desired in multi_devices_sync.desired_process:
desired.start()
# 等所有进程结束后关闭
for desired in multi_devices_sync.desired_process:
desired.join()
补充:
1.进程和线程的区别?
进程是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。
线程有时也被称为轻量级进程,是程序执行流的最小单元。线程是进程中的一个实体,一个进程可以包含多个线程,但是线程不能包含多个进程。线程自己不拥有系统资源,在单个程序中同时运行多个线程完成不同的工作,成为多线程。
区别:
数据空间的分配,子进程和父进程有不同的代码和数据空间,而多个线程则共享数据空间,每个线程有自己的执行堆栈和程序计数器为其执行上下文。
可以将进程看成是一个工厂,多个进程就是多个工厂;把线程看成是工厂里面的流水线,一个工厂中可以同时有多个流水线。
福利
以上是关于python+appium 自动化测试-Appium 并发测试之多设备启动的主要内容,如果未能解决你的问题,请参考以下文章
基于appium实现的线性代码引用unittest单元测试框架
python+appium自动化测试 —— Appium并发测试之python启动appium服务
Appium (Android):应用程序未使用调试证书签名