网易首页 > 网易号 > 正文 申请入驻

高阶测试:Appium集成openSTF实现多设备并发执行用例

0
分享至

一、应用场景:

你是否有这样的困惑:通过appium+testng已经写好一个个移动端自动化用例了,单个用例运行也没有什么问题,但是真实的企业应用场景是筛选一批合适的用例同时运行,无人值守,那下面这个案例将是一个本人已实践过的方案,希望能带给你相关的思考。

二、本文案例环境配置:

  • 搭建好openSTF服务,并连接至少2台移动设备(或模拟器)。

http://www.360doc.com/showweb/0/0/983537700.aspx

  • 编写appium+testng安卓端自动化用例。
  • 安装nodejs并通过nodejs安装appium。

http://www.360doc.com/content/21/0528/18/8189294_979429344.shtml

  • 基本思路图:

注:

本文仅作为一个思路引导,真正的实践其实是根据公司现有的自动化成果来做调整的,读者可将里面对你有用的东西引入进你自己的自动化中。

接下来将根据上述图示来写代码,本文的重点是与openStf相关的内容,关于appium自动化用例如何编写,appium如何批量运行,怎样介入mq等不在本文范围。

三、appium并发执行的2种思路:

3.1、 hub--node的方式(即selenium grid + appium node)

如下图,它的grid其实就用的是selenium的grid,他们是通用的,只是web端你需要将浏览器node关联至grid,而移动端与grid关联的就是一个个appium server,每个appium server再去连接一台移动设备。

此种方式需要在用例运行前即把每台移动设备与appium server连接好,然后用例运行时grid即去将用例分发至每个appium node上去执行。

我们当前没有采用该种方式,考虑到移动设备需要充分利用,使用该种方式有局限性。---从当前了解到的知识来看,后续或许能找到相关解决方案。


3.2、动态启appium服务(随时用随时启,只要有空闲移动设备)

这是由appium本身的工作机制决定,因为一个appium服务,只能与一台移动设备通信,而要实现并发,那就需要多启几个服务,且每个服务都要连接一台手机。

而在本案例中即通过在用例执行时去动态启动appium服务,并连接到空闲移动设备。

四、代码实现:

1)启动appium server

public class AppiumServer {

private static AppiumServiceBuilder appiumServicebuilder;

private static AppiumDriverLocalService appiumService;

public static URL getAppiumUrl (){

logger.info("获取Ip:"+appiumService.getUrl().toString());

return appiumService.getUrl();

public static void startServer(){

//启动appium服务

appiumServicebuilder = new AppiumServiceBuilder();

appiumServicebuilder.withIPAddress("127.0.0.1");//此处ip无法动态,手机必须连接在服务启动的电脑

int port = Integer.parseInt("47"+ RandomUtil.nextInt(89));

logger.info("Random appium server port is:"+port);

if (!checkAppiumServerIsRunning(port)){

appiumServicebuilder.usingPort(port);//需要改成动态的

appiumServicebuilder.withArgument(GeneralServerFlag.SESSION_OVERRIDE);

appiumServicebuilder.withArgument(GeneralServerFlag.LOG_LEVEL,"error");//暂时不知道是哪里的日志级别

//appiumService = AppiumDriverLocalService.buildDefaultService();

appiumService = AppiumDriverLocalService.buildService(appiumServicebuilder);

appiumService.start();

2)启动appium driver

public class MyAndroidKeyMobileDriver{

* 启动driver

public static WebDriver getDriver(ITestContext context) {

WebDriver driver = null;

DesiredCapabilities desiredCapabilities = null;

try {

desiredCapabilities = BaseDriven.setAndroidCapabilities(context);

//新增的代码

driver = new AndroidDriver<>(AppiumServer.getAppiumUrl(), desiredCapabilities);

DriverCache.set(driver);

driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);

logger.info("appium android 成功启动 APP Package [ " +

desiredCapabilities.getCapability(AndroidMobileCapabilityType.APP_PACKAGE) + " ]。");

}catch ( WebDriverException e ) {

if (e.getMessage().contains("Connection refused: ")) {

logger.error("Appium Desktop 服务器未启动,请检查,谢谢。");

if (e.getMessage().contains("not find app package")) {

assert desiredCapabilities != null;

logger.error("Android app【 " + desiredCapabilities.getCapability

(AndroidMobileCapabilityType.APP_PACKAGE) + " ] 不存在。");

logger.error("App启动异常:", e);

return driver;

注:stf提供了关于操作所挂载的设备相关接口,只要把stf服务启动起来即可访问

3)通过stf api操作设备

* 获取所有设备

public static List getAllDevices(){

Map stfHeaderMap = new HashMap();

Map paramMap = new HashMap();

stfHeaderMap.put("Authorization","Bearer "+ACCESS_TOKEN);

String response = httpClientAdaptor.doGet(STF_SERVICE_URL + "devices",stfHeaderMap,paramMap);//查询所有的设备

Map maps = JsonUtil.toObject(response, Map.class); // json转换为Map

String devices = String.valueOf(maps.get("devices")); // 获取设备列表,是一个json数组

System.out.println("所有的设备信息:"+devices);

//将json数组转化为

List deviceList = new ArrayList<>();

JSONArray array = JsonUtil.toJSONArray(devices);

for (int i = 0;i

DeviceEntity deviceEntity = new DeviceEntity();

JSONObject obj = (JSONObject) array.get(i);

deviceEntity.setSerial(obj.getString("serial"));

deviceEntity.setPlatform(obj.getString("platform"));

deviceEntity.setVersion(obj.getString("version"));

deviceEntity.setRemoteConnectUrl(obj.getString("remoteConnectUrl"));

deviceEntity.setUsing(Boolean.parseBoolean(obj.getString("using")));

deviceEntity.setReady(Boolean.parseBoolean(obj.getString("ready")));

deviceEntity.setPresent(Boolean.parseBoolean(obj.getString("present")));

String providerJson = obj.getString("provider");

Map providerMaps = JsonUtil.toObject(providerJson, Map.class);

String providerName = (String) providerMaps.get("name");

deviceEntity.setProvider(providerName);

deviceList.add(deviceEntity);

System.out.println("设备个数:"+deviceList.size());

return deviceList;

* 查找空闲设备并锁定

public static String connectFreeDevice(String slaveMachine){

String currentConnectedDevice = null;

List deviceList = getAllDevices();

for (Iterator itr = deviceList.iterator(); itr.hasNext();) {

DeviceEntity device = (DeviceEntity) itr.next();

//获取对应编译机上挂载的手机设备

if (device.getProvider().contains(slaveMachine)){

if (!device.isPresent() || !device.isReady() || device.isUsing()){

//logger.error("device is in use!");

continue;

//找到空闲即申请使用

currentConnectedDevice = device.getSerial();

addDeviceToUser(currentConnectedDevice);

logger.info("Find free device:"+currentConnectedDevice);

break;

return currentConnectedDevice;

* 锁定设备,标识被某个stf的账户占用

private static boolean addDeviceToUser(String serial){

String reqJson = "{\"serial\": \""+serial+"\"}";

Map stfHeaderMap = new HashMap();

Map paramMap = new HashMap();

stfHeaderMap.put("Authorization","Bearer "+ACCESS_TOKEN);

stfHeaderMap.put("Content-Type","application/json; charset=utf-8");

String response = httpClientAdaptor.doPost(STF_SERVICE_URL + "user/devices",stfHeaderMap,reqJson);

logger.info("mq 端锁定设备响应消息:"+response);

Map maps = JsonUtil.toObject(response, Map.class); // json转换为Map

if (!Boolean.parseBoolean(String.valueOf(maps.get("success")))) {

logger.error("Device not found");

return false;

logger.info("The device ["+serial+"]is locked successfully");

return true;

* 释放设备(用例用完以后,将该设备重新置为空闲)

public static void releaseDevice(String serial) {

Map paramMap = new HashMap();

Map stfHeaderMap = new HashMap();

stfHeaderMap.put("Authorization","Bearer "+stfService.getAuthToken());

String response = httpClientAdaptor.doDelete(stfService.getStfUrl() + "user/devices/"+serial,stfHeaderMap,"");

logger.info("释放设备接口返回信息:"+response);

4)用例层调用上述方法:

package cn.study.testapi.base.support;

import cn.study.testapi.base.enums.DrivenEnum;

import cn.study.testapi.base.load.InitLoadNew;

import cn.study.testapi.core.appium.server.AppiumServer;

import cn.study.testapi.core.driver.driven.factory.KeyDriverFactory;

import cn.study.testapi.core.driver.keydriver.AndroidKeyDriver;

import cn.study.testapi.core.openstf.DeviceApi;

import cn.study.testapi.utils.*;

import cn.study.testapi.core.keyaction.AndroidKeyAction;

import cn.study.testapi.core.entity.ComponentStep;

import org.apache.log4j.Logger;

import org.testng.ITestContext;

import org.testng.annotations.*;

import java.util.List;

public class AndroidKeywordTest extends BaseKeyTest {

protected static Logger logger = Logger.getLogger(AndroidKeywordTest.class);

protected AndroidKeyDriver driver = null;

//在testng suit之前启动appium server

@Parameters({"deviceSerial"})

@BeforeSuite(alwaysRun = true)

public void setUp(@Optional("deviceSerial") String deviceSerial, ITestContext context) {

InitLoadNew initLoadNew = new InitLoadNew(odinEnv, taskId);

// 初始化接口返回result

setCaseStepList(initLoadNew.getCaseStepList());

AppiumServer.startServer();//启动appium server

driver = MyAndroidKeyMobileDriver.getDriver(context); // 启动android app,根据自己的项目结构去设计此处获取driver的方式

@Test(alwaysRun = true, dataProvider = "keyword")

public void testCaseStep(List data) {

//执行你的用例

//aftersuit执行的动作,此处传一个【设备序列】参数,指明要释放的设备

@Parameters({"deviceSerial"})

@AfterSuite(alwaysRun = true)

public void tearDown(@Optional("deviceSerial") String deviceSerial) {

logger.info("========= tearDown ========");

DeviceApi.releaseDevice(deviceSerial);//释放移动设备

AppiumServer.stopAppiumServer();//用例执行完后停掉服务

JdbcUtil.close();

TempFileUtil.deleteOnExit();

driver.quit();

代码写完以后,你就可以尝试并行执行多条android端自动化用例看看效果啦。

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
网传大厂女员工被裁!带着260万回老家种地,每月利息4961.21元…

网传大厂女员工被裁!带着260万回老家种地,每月利息4961.21元…

火山诗话
2024-05-08 10:42:06
梅大高速悲剧后,国家数据局应该做些什么?

梅大高速悲剧后,国家数据局应该做些什么?

古装影视解说阿凶
2024-05-08 16:17:22
高亚麟魏嘉同框画面曝光,二人有说有笑关系密切,当时已产女一年

高亚麟魏嘉同框画面曝光,二人有说有笑关系密切,当时已产女一年

萌神木木
2024-05-08 20:12:09
NBA官宣常规赛MVP:约基奇四年三次当选太强 比肩四大名宿

NBA官宣常规赛MVP:约基奇四年三次当选太强 比肩四大名宿

罗说NBA
2024-05-09 07:34:06
哈马斯沦为弃子,已成瓮中捉鳖

哈马斯沦为弃子,已成瓮中捉鳖

清哲木观察
2024-05-08 12:46:47
27岁怀孕少妇遇害,有80位暧昧对象,体内竟然检测到2个男人的DNA

27岁怀孕少妇遇害,有80位暧昧对象,体内竟然检测到2个男人的DNA

胖胖侃咖
2024-05-09 08:00:08
老戏骨人设崩塌!高亚麟把北影校花当鸡睡,喜欢家暴后“来一发”

老戏骨人设崩塌!高亚麟把北影校花当鸡睡,喜欢家暴后“来一发”

娱乐哈哈酱
2024-05-08 13:57:45
曝美国一女子从事特殊行业,去年从业收入锐减64%!预测:经济衰退了

曝美国一女子从事特殊行业,去年从业收入锐减64%!预测:经济衰退了

小萝卜丝
2024-05-08 14:07:48
左宗棠收复新疆之战:不留生俘,降了也杀!以此换来30年安定

左宗棠收复新疆之战:不留生俘,降了也杀!以此换来30年安定

知否否
2024-04-20 11:48:05
逼良为娼,被强迫拍了50部三级片:从车模到女优,她只走错了一步

逼良为娼,被强迫拍了50部三级片:从车模到女优,她只走错了一步

爱过的人去了哪里
2022-06-19 16:40:26
加沙停火谈判最新进展!以军称打死哈马斯一指挥官,公布地面部队进入拉法视频!美国暂停向以色列交付......

加沙停火谈判最新进展!以军称打死哈马斯一指挥官,公布地面部队进入拉法视频!美国暂停向以色列交付......

每日经济新闻
2024-05-09 06:28:21
女儿看上我每月一万八的退休金,让我照顾瘫痪婆婆,最终陷入癫狂

女儿看上我每月一万八的退休金,让我照顾瘫痪婆婆,最终陷入癫狂

大花谈教育
2024-05-07 11:01:27
359比43,约翰逊的议长职位保住了

359比43,约翰逊的议长职位保住了

寰宇大观察
2024-05-09 09:51:50
医学大V:中医药在医疗费用中比重过高,老百姓只能用便宜但效果不佳的国产药

医学大V:中医药在医疗费用中比重过高,老百姓只能用便宜但效果不佳的国产药

互联网大聪明
2024-05-09 07:20:44
后续!辱华留学生已被刑拘,家庭背景被扒,真实身份曝光!

后续!辱华留学生已被刑拘,家庭背景被扒,真实身份曝光!

叶公子
2024-05-08 06:37:26
广州天桥下竖切大片砖块惹市民不满,四周还用铁丝网封锁

广州天桥下竖切大片砖块惹市民不满,四周还用铁丝网封锁

映射生活的身影
2024-05-08 22:01:51
雷霆记者吐槽:谁给亚历山大投了一张第五选票啊

雷霆记者吐槽:谁给亚历山大投了一张第五选票啊

直播吧
2024-05-09 08:24:16
23岁性感女星逛街遭男性骚扰跟踪,发文痛斥:真的很害怕

23岁性感女星逛街遭男性骚扰跟踪,发文痛斥:真的很害怕

文艺圈娱乐号
2024-05-09 09:09:16
陈冰:TikTok起诉拜登政府,终局是什么?

陈冰:TikTok起诉拜登政府,终局是什么?

直新闻
2024-05-08 22:23:11
为了恐吓村民,镇政府开出了罚单,自造了一部法律,还委托村里收缴罚款

为了恐吓村民,镇政府开出了罚单,自造了一部法律,还委托村里收缴罚款

法律学堂
2024-05-09 00:06:25
2024-05-09 12:02:44
51Testing软件测试网
51Testing软件测试网
中国软件测试人的精神家园
1519文章数 13253关注度
往期回顾 全部

科技要闻

百度副总裁道歉:初心是做好工作 但太急了

头条要闻

雷蒙多:美国可采取"极端措施"禁止中国联网汽车入美

头条要闻

雷蒙多:美国可采取"极端措施"禁止中国联网汽车入美

体育要闻

雷霆三少2.0,最大的不同点在哪?

娱乐要闻

高亚麟魏嘉同框画面曝光,当时已产女

财经要闻

全球央行大乱战!美日南辕北辙 瑞典降息

汽车要闻

蔚来第二品牌乐道将于5月15日正式发布

态度原创

旅游
手机
艺术
家居
房产

旅游要闻

昆明一民宿辱骂威胁游客 店家:没忍住

手机要闻

夏普 Aquos R9 和 Aquos wish4 发布

艺术要闻

中国嘉德2024春拍第一阶段预展揭幕!吴大羽油画力作亮相

家居要闻

知行空间 消弭生活的界限

房产要闻

港岛南区:从富人聚居地到“Blue Coast”的活力与机遇

无障碍浏览 进入关怀版