Appium并发测试
参考官方文档解释:
Appium 给用户提供了在一个机器上启动多个 Android sessions 的方案。该方案只需要通过不同参数来启动的多个 Appium 服务。
以下是启动多个 Android 会话的一些重要参数:
-p
Appium 主要端口-U
设备 id-bp
Appium bootstrap 端口--chromedriver-port
chromedriver 端口 (若是在使用 webviews 或 chrome)--selendroid-port
selendroid 端口 (若是在使用 selendroid)
更多相关参数的信息可以参考 这里 。
如果我们有两台设备,且他们的设备 id 分别为 43364 和 32456,我们可以通过以下命令启动两个不同的 Appium 服务器:
node . -p 4492 -bp 2251 -U 32456
node . -p 4491 -bp 2252 -U 43364
只要你的 Appium 与 Appium bootstrap 的端口在 0 到 65536 之间,且端口号并不相同,这样两个 Appium 服务器就不会去监听同一个端口。确保通过 -u 参数标志的 id 与对应的设备 id 是一致的。这就是 Appium 能知道设备之间是如何通信的原因,因此必须保证参数准确无误。
如果你使用 chromedriver 或 selendroid,记得确保服务器的端口号是独一无二的。
如果你使用 appium-uiautomator2-driver, 需要给 systemPort 这个 capability 配置为不同的系统端口。因为有时候如果没有使用不同的端口,会出现冲突,比如这个问题.
所以Capability必须要加上systemPort
systemPort
用于连接appium-uiautomator2-server默认值是8200
,并行测试时,必须调整端口以避免冲突。
Parallel Android Tests
Appium provides a way for users to automate multiple Android sessions on a single machine on single server instance. All it involves is starting Appium server on any available port.
The important capabilities:
udid
the device idchromeDriverPort
the chromedriver port (if using webviews or chrome)systemPort
If you are using appium-uiautomator2-driver, set a different system port for each android session, set withsystemPort
capability since sometimes there can be a port conflict if different ports aren't used, such as in this issue.
代码:
#encoding:utf8
from utils.YamlUtil import YamlReader
from conf import Conf
from appium import webdriver
#1、通过yaml来读取caps.yml
reader = YamlReader(Conf.conf_caps)
data = reader.data()
#2、结果,字典转换
def appium_desired_caps(host,port,systemPort="8200"):
#2、desired创建字典
desired_caps=dict()
#3、platformName
desired_caps['platformName'] = data['platformName']
#4、platformVersion
desired_caps['platfromVersion']=data['platfromVersion']
#5、deviceName
desired_caps['deviceName'] = data['deviceName']
#6、启动程序的包名appPackage
desired_caps["appPackage"] = data['appPackage']
#7、启动界面名appActivity
desired_caps['appActivity'] = data['appActivity']
#解决中文
desired_caps["unicodeKeyboard"] = data['unicodeKeyboard']
desired_caps["resetKeyboard"] = data['resetKeyboard']
#获取toast automationName = uiautomator2
desired_caps["automationName"] = data['automationName']
#不清除app里的原有数据
desired_caps["noReset"] = data["noReset"]
#解决并发测试
desired_caps["systemPort"] = systemPort
# 8、http,连接appium服务器
driver = webdriver.Remote('http://%s:%s/wd/hub'%(host,port), desired_caps)
driver.implicitly_wait(20)
return driver
caps.yml
#platformName
platformName: 'Android'
#platformVersion
platfromVersion: '8.0'
#deviceName
deviceName: 'Google'
#启动程序的包名appPackage
appPackage: 'com.boxuegu'
#启动界面名appActivity
appActivity: 'com.boxuegu.activity.MainFlutterActivity'
#解决中文
unicodeKeyboard: True
resetKeyboard: True
#启动app时不要清除app里的原有的数据
noReset: True
#获取toast automationName = uiautomator2
automationName: 'uiautomator2'
启动脚本
import concurrent.futures
import pytest
from base.Allure_Report import allure_generate
from conf import Conf
import os
# 1.方法实现
def run_pytest(device):
report_path = Conf.report_path + os.sep + "result"+os.sep+device["name"]
report_html = Conf.report_path + os.sep + "html" +os.sep+device["name"]
pytest.main([f"--cmdopt={device}","--alluredir",report_path])
# time.sleep(2)
allure_generate(report_path, report_html)
# 3.pool并发
def run_pool(devices):
with concurrent.futures.ProcessPoolExecutor(len(devices)) as executor:
executor.map(run_pytest,devices)
if __name__ == '__main__':
# 2.参数列表
devices_list= list()
device_1 = { "host":"127.0.0.1",
"port":"4723",
"bpport":"4724",
"udid":"192.168.56.104:5555",
"systemPort":8200,
"name": "华为mate9"}
device_2 = { "host":"127.0.0.1",
"port":"4725",
"bpport":"4726",
"udid":"192.168.56.105:5555",
"systemPort": 8201,
"name": "华为mate10"}
devices_list.append(device_1)
devices_list.append(device_2)
run_pool(devices_list)