app并发量测试怎么做_app⾃动化测试-多设备并发-
appium+pytest+多线程
1、appium+python 实现单设备的 app ⾃动化测试
1. 启动 appium rver,占⽤端⼝ 4723
2. 电脑与⼀个设备连接,通过 adb devices 获取已连接的设备
3. 在 python 代码当中,编写启动参数,通过 pytest 编写测试⽤例,来进⾏⾃动化测试。草字头加个今
2、若要多设备并发,同时执⾏⾃动化测试,那么需要:
1. 确定设备个数
2. 每个设备对应⼀个 appium rver 的端⼝号,并启动 appium
3. pytest 要获取到每个设备的启动参数,然后执⾏⾃动化测试。
3、实现策略
第⼀步:从设备池当中,获取当前连接的设备。若设备池为空,则⽆设备连接。
第⼆步:若设备池不为空,启动⼀个线程,⽤来启动appium rver.与设备个数对应。
起始rver端⼝为4723,每多⼀个设备,端⼝号默认+4
第三步:若设备池不为空,则启⽤多个线程,来执⾏app⾃动化测试。
4、具体实现步骤
4.1 通过 adb 命令,获取当前已连接的设备数、设备名称、设备的安卓版本号。
定义⼀个 ManageDevices 类。
1. 重启adb服务。
2. 通过adb devices命令获取当前平台中,已连接的设备个数,和设备uuid.
3. 通过adb -P 5037 -s 设备uuid shell getprop ro.lea获取每⼀个设备的版本号。
4. 将所有已连接设备的设备名称、设备版本号存储在⼀个列表当中。
5. 通过调⽤get_devices_info函数,即可获得4中的列表。
实现的部分代码为:
"""
@Title : app多设备并发-appium+pytest
@Author : 柠檬班-⼩简
@Email : lemonban_
"""
class ManageDevices:
"""
1、重启adb服务。
2、通过adb devices命令获取当前平台中,已连接的设备个数,和设备uuid.
3、通过adb -P 5037 -s 设备uuid shell getprop ro.lea获取每⼀个设备的版本号。
4、将所有已连接设备的设备名称、设备版本号存储在⼀个列表当中。
5、通过调⽤get_devices_info函数,即可获得4中的列表。
"""
def __init__(lf):
lf.__devices_info = []
# 重启adb服务
lf.__run_command_and_get_stout("adb kill-rver")
lf.__run_command_and_get_stout("adb start-rver")
def get_devices_info(lf):
"""
获取已连接设备的uuid,和版本号。
鬼纹
:return: 所有已连接设备的uuid,和版本号。
"""
lf.__get_devices_uuid()
print(lf.__devices_info)
lf.__get_device_platform_vesion()
return lf.__devices_info
4.2 定义⼀个设备配置池。
设备启动参数管理池。
每⼀个设备:对应⼀个启动参数,以及appium服务的端⼝号。
1. desired_caps_config/desired_caps.yaml⽂件中存储了启动参数模板。
2. 从1中的模板读取出启动参数。
3. 从设备列表当中,获取每个设备的设备uuid、版本号,与2中的启动参数合并。
4. 每⼀个设备,指定⼀个appium服务端⼝号。从4723开始,每多⼀个设备,默认递增4
5. 每⼀个设备,指定⼀个本地与设备tcp通信的端⼝号。从8200开始,每多⼀个设备,默认递增4.
在启动参数当中,通过systemPort指定。
因为appium服务会指定⼀个本地端⼝号,将数据转发到安卓设备上。
默认都是使⽤8200端⼝,当有多个appium服务时就会出现端⼝冲突。会导致运⾏过程中出现socket hang up的报错。实现的部分代码:
def devices_pool(port=4723,system_port=8200):
"""
设备启动参数管理池。含启动参数和对应的端⼝号
:param port: appium服务的端⼝号。每⼀个设备对应⼀个。
:param system_port: appium服务指定的本地端⼝,⽤来转发数据给安卓设备。每⼀个设备对应⼀个。 :return: 所有已连接设备的启动参数和appium端⼝号。
"""
desired_template = __get_yaml_data()
devs_pool = []
# 获取当前连接的所有设备信息
m = ManageDevices()
all_devices_info = m.get_devices_info()
# 补充每⼀个设备的启动信息,以及配置对应的appium rver端⼝号
if all_devices_info:
for dev_info in all_devices_info:
dev_info.update(desired_template)
dev_info["systemPort"] = system_port
new_dict = {
"caps": dev_info,
"port": port
}
devs_pool.append(new_dict)
port += 4
system_port += 4
return devs_pool
特别注意事项:
2 个及 2 个以设备并发时,会遇到设备 socket hang up 的报错。征服的英文
原因是什么呢:
在 appium rver 的⽇志当中,有这样⼀⾏ adb 命令:
adb -P 5037 -s 08e7c5997d2a forward tcp:8200 tcp:6790
什么意思呢?
将本地 8200 端⼝的数据,转发到安卓设备的 6790 端⼝
所以,本地启动多个 appium rver,都是⽤的 8200 端⼝,就会出现冲突。
解决⽅案:
应该设置为,每⼀个 appium rver ⽤不同的本地端⼝号,去转发数据给不同的设备。
systemPort= 端⼝号 来设置。
启动参数当中:添加 systemPort= 端⼝号
这样,每个设备都使⽤不同的本地端⼝,那么可解决此问题。
4.3 appium rver 启停管理。
(ps 此处可以使⽤ appium 命令⾏版,也可以使⽤桌⾯版)
1. 在⾃动化⽤例运⾏之前,必须让 appium rver 启动起来。
2. 在⾃动化⽤例执⾏完成之后,要 kill 掉 appium 服务。这样才不会影响下⼀次运⾏。
代码实现如下:
import subprocess
白银杀人
import os
不成人之恶上一句from Common.handle_path import appium_logs_dir
class ManageAppiumServer:
"""
appium desktop通过命令⾏启动appium服务。
不同平台上安装的appium,默认的appium服务路径不⼀样。
初始化时,设置appium服务启动路径
再根据给定的端⼝号启动appium
"""
def __init__(lf,appium_rver_apth):
lf.rver_apth = appium_rver_apth
# 启动appium rver服务
def start_appium_rver(lf,port=4723):
appium_log_path = os.path.join(appium_logs_dir,"appium_rver_{0}.log".format(port))
command = "node {0} -p {1} -g {2} "
"--ssion-override "
"--local-timezone "
"--log-timestamp & ".format(lf.rver_apth, port, appium_log_path)
subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE,shell=True).communicate()
# 关闭appium服务
@classmethod
def stop_appium(cls,pc,post_num=4723):
'''关闭appium服务'''
if pc.upper() == 'WIN':
p = os.popen(f'netstat -aon|findstr {post_num}')
p0 = p.read().strip()
if p0 != '' and 'LISTENING' in p0:
p1 = int(p0.split('LISTENING')[1].strip()[0:4]) # 获取进程号
os.popen(f'taskkill /F /PID {p1}') # 结束进程
print('appium rver已结束')
职员招聘
elif pc.upper() == 'MAC':
p = os.popen(f'lsof -i tcp:{post_num}')
p0 = p.read()
if p0.strip() != '':
p1 = int(p0.split('n')[1].split()[1]) # 获取进程号
os.popen(f'kill {p1}') # 结束进程
print('appium rver已结束')
4.4 pytest 当中根据不同的启动参数来执⾏⾃动化测试⽤例
在使⽤ pytest 执⾏⽤例时,是通过 pytest.main()会⾃动收集所有的⽤例,并⾃动执⾏⽣成结果。
这种情况下,appium 会话的启动信息是在代码当中给定的。
火星弟弟
以上模式当中,只会读取⼀个设备的启动信息,并启动与设备的会话。如何包花
虽然 fixture 有参数可以传递多个设备启动信息,但它是串⾏执⾏的。
需要解决的问题的是:
1. 可以传递多个设备的启动参数,但不是通过 fixture 的参数。
2. 每传递⼀个设备启动参数进来,执⾏⼀次 pytest.main()
解决⽅案:
1. 通过 pytest 的命令⾏参数。即在 pytest.main()的参数当中,将设备的启动信息传进来。
2. 使⽤ python 的多线程来实现。每接收到⼀个设备启动参数,就启动⼀个线程来执⾏ pytest.main 4.4.1 第⼀个,pytest 的命令⾏参数。
⾸先需要在 conftest.py 添加命令⾏选项,命令⾏传⼊参数”--cmdopt“。
⽤例如果需要⽤到从命令⾏传⼊的参数,就调⽤ cmdopt 函数。