文章目录
前言
对于一个公司来说,测试设备肯定不止一台,为了使公司的App更大化兼容市面上的机型和系统,所以配备几十台设备,都是正常的,所以就要求UI自动化,能不能实现多机同时并行各自运行相同的用例。
多机同时执行相同的用例,更多涉及到一个App新增或修改了功能之后,查看各个设备是否有兼容问题的情况。
要实现多机同时执行用例,那么之前的写死desired_capabilities的方案肯定是行不通的,需要系统根据现有通过usb连接到电脑的设备列表,来自动配置对应的desired_capabilities。
一、组装desired_capabilities信息
1、系统识别当前usb连接设备信息
参照源码 leiyong711/iOS_Ui_Automation,封装了shell工具:
class Shell:
def __init__(self):
pass
@staticmethod
def invoke(cmd):
output, errors = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
o = output.decode("utf-8")
print(o)
return o
然后使用操作iOS设备的libimobiledevice工具获取当前多个设备的信息。
如果没有libmobiledevice的话,可以执行brew install libimobiledevice安装
# 获取所有设备的udid信息,返回字符串,udid与udid之间以换行符间隔,所以可以以换行符来split。
str_udid = Shell.invoke('idevice_id -l')
udids = str_udid.strip('\n').split('\n')
# 获取设备版本信息
outputVersion = Shell.invoke('ideviceinfo -u %s -k ProductVersion' % udid)
# 获取设备名称,就是用户自己设置的“xxx的iPhone”那一项
output_name = Shell.invoke('idevicename -u %s' % udid)
2、不同设备设置不同的wda端口号
在desired_capabilities配置中,有专门设置wda的参数,一个是设置Appium的wdaLocalPort,默认8100,一个是设置远端也就是手机上的wda的端口的wdaRemotePort,默认也是8100。
对于Appium server来说,它只有一个8100端口,所以如果要同时连接多个设备,不同设备需要设置不同的wdaLocalPort端口。
而wdaRemotePort,是相对于设备的端口,可以都默认8100。但是我没有试过,我是两个端口都一致,比如设备A的local和remote都是8100,设备B都是8104。
wdaRemotePort只对执行用例前未启动wda的情况才有效,设备启动wda时按照这个配置来使用端口
3、关于Appium端口4723
不论是本文写的关于多机同时并行执行相同用例的情况,还是下一篇文章要提的,多机同时执行不同用例达到多个用户在App里交互的效果,都是使用同一个Appium的同一个端口4723,所以不需要单独给不同设备设置不同的端口。
然后再加上desired_capabilities中常规的参数,这样,配置就搞定了。
二、使用pytest的xdist插件实现多机并行
首先使用pytest-xdist插件,需要安装:
pip3 install pytest-xdist
然后参照YouTube中这个视频里的使用方法,把参数化用在pytest的fixture功能里,我们先来看看baidu的AI提供的使用示例:
import pytest
@pytest.fixture(params=[1, 2, 3])
def numbers(request):
return request.param
def test_example(numbers):
print(f"Testing with number: {numbers}")
按照示例,参数等于1、等于2、等于3的用例会开启不同的线程同时执行。那么我们把不同设备信息放到dict里,不同dict放到一个list里,params=这个list。那么执行的时候,就可以实现多机同时执行相同用例了。
为了直观,放下我的代码demo:
from appium.options.ios.xcuitest.base import XCUITestOptions
from appium import webdriver
@pytest.fixture(params=Device.get_devices(), scope="session")
def multi_enter_app(request):
print("++++++++++++多设备用例执行前++++++++++++++++++++++++++")
host = request.param["host"]
user = request.param["user"]
env = request.param["env"]
fs = open(os.path.join(desired_caps_dir, "iOS_desired_capabilities.yaml"), encoding="utf-8")
desired_caps = yaml.load(fs, Loader=yaml.FullLoader)
desired_caps["udid"] = request.param["udid"]
desired_caps["wdaRemotePort"] = request.param["wdaPort"]
desired_caps["wdaLocalPort"] = request.param["wdaPort"]
desired_caps["platformVersion"] = request.param["platformVersion"]
options = XCUITestOptions()
options.load_capabilities(desired_caps)
driver = webdriver.Remote(host, options=options)
yield {"driver": driver, "user": user, "env": env}
print("=============多设备测试用例之后的==========")
driver.quit()