Appium [已解决] 一台电脑开启两个 Appium 客户端,分别控制两台测试设备进行联动测试

剪烛 · July 02, 2015 · Last by 丫丫 replied at March 27, 2017 · 6568 hits

需求

对两台测试设备进行测试,一台测试设备为Android设备,一台为iOS设备,类似用iPhone充当遥控器控制一台Android盒子。
因为手上暂时并没有mac环境,暂时用两台Android设备测试。

操作

电脑开启两个Appium客户端,将其中一个客户端的端口改为:4725
运行后,验证了两个地址都正常返回: http://127.0.0.1:4723/http://127.0.0.1:4725/

client端代码

DesiredCapabilities capabilities = new DesiredCapabilities(); 
capabilities.setCapability("device","Android");
capabilities.setCapability("deviceName", "b1d12c6");
capabilities.setCapability("platformVersion", "4.4.4");
capabilities.setCapability("platformName", "Android");
capabilities.setCapability("appPackage", "com.my.pkg");
capabilities.setCapability("appActivity", "com.my.pkg.LoadingActivity");
driver = new AndroidDriver(new URL("http://127.0.0.1:4723/wd/hub"), capabilities);

DesiredCapabilities capabilities2 = new DesiredCapabilities();
capabilities2.setCapability("device","Android");
capabilities2.setCapability("deviceName", "0123456789ABCDEF");
capabilities2.setCapability("platformVersion", "4.4.4");
capabilities2.setCapability("platformName", "Android");
capabilities2.setCapability("appPackage", "com.my.pkg");
capabilities2.setCapability("appActivity", "com.my.pkg.LoadingActivity");
driver2 = new AndroidDriver(new URL("http://127.0.0.1:4725/wd/hub"), capabilities2);

执行结果

client端:
deviceName=b1d12c6 找不到Session

org.openqa.selenium.remote.SessionNotFoundException: 
Command duration or timeout: 5 milliseconds
Build info: version: '2.45.0', revision: '5017cb8', time: '2015-02-26 23:59:50'
System info: host: 'RMTCNW20054', ip: '192.168.21.48', os.name: 'Windows 7', os.arch: 'amd64', os.version: '6.1', java.version: '1.7.0_67'
Session ID: edc5d7c6-892f-401d-8f26-049d0ffab5eb
Driver info: io.appium.java_client.android.AndroidDriver
Capabilities [{platform=LINUX, javascriptEnabled=true, appActivity=com.runmit.sweedee.LoadingActivity, browserName=Android, networkConnectionEnabled=true, desired={platformVersion=4.4.4, platformName=Android, deviceName=b1d12c6, appActivity=com.runmit.sweedee.LoadingActivity, device=Android, appPackage=com.runmit.sweedee}, locationContextEnabled=false, appPackage=com.runmit.sweedee, platformVersion=4.4.4, databaseEnabled=false, platformName=Android, deviceName=0123456789ABCDEF, webStorageEnabled=false, device=Android, warnings={}, takesScreenshot=true}]
......

测试设备:
被测程序在一台机器(deviceName=0123456789ABCDEF)启动了两次,而另外一台机器没有任何执行。
Appium日志:
4723端口的Appium服务端的日志中,deviceName从b1d12c6变成了0123456789ABCDEF

info: --> POST /wd/hub/session {"desiredCapabilities":{"platformVersion":"4.4.4","deviceName":"b1d12c6","platformName":"Android","appActivity":"com.runmit.sweedee.LoadingActivity","device":"Android","appPackage":"com.runmit.sweedee"}}
info: Client User-Agent string: Apache-HttpClient/4.3.6 (java 1.5)
info: [debug] The following desired capabilities were provided, but not recognized by appium. They will be passed on to any other services running on this server. : device
info: [debug] Didn't get app but did get Android package, will attempt to launch it on the device
info: [debug] Creating new appium session 05488004-2912-4243-ad70-690ebaf420e3
info: Starting android appium
info: [debug] Getting Java version
info: Java version is: 1.7.0_67
info: [debug] Checking whether adb is present
info: [debug] Using adb from D:\software\adt-bundle-windows-x86_64-20140702\sdk\platform-tools\adb.exe
warn: No app capability, can't parse package/activity
info: [debug] Set chromedriver binary as: C:\Program Files (x86)\Appium\node_modules\appium\build\chromedriver\windows\chromedriver.exe
info: [debug] Using fast reset? true
info: [debug] Preparing device for session
info: [debug] Not checking whether app is present since we are assuming it's already on the device
info: Retrieving device
info: [debug] Trying to find a connected android device
info: [debug] Getting connected devices...
info: [debug] executing cmd: D:\software\adt-bundle-windows-x86_64-20140702\sdk\platform-tools\adb.exe devices
info: [debug] 2 device(s) connected
info: Found device 0123456789ABCDEF
info: [debug] Setting device id to 0123456789ABCDEF
.......之后所有的日志中的deviceName全部为0123456789ABCDEF

从现象上看,好像是client发送的json信息中deviceName 确实是b1d12c6,但是Appium在执行时,将deviceid 设置成了另一台的测试设备的deviceName 0123456789ABCDEF
导致设备0123456789ABCDEF上运行了两次脚本

这是为什么?

是Appium本身不支持电脑运行多个服务端?还是我client的bug?

两台电脑分别运行Appium服务端

两台电脑分别运行Appium服务端,端口的ip改为电脑真实的ip,然后通过脚本操作两个Appium服务端分别控制两个测试设备,这样是OK的。但是平白多浪费一台电脑,感觉实在有点浪费。

解决方法

设置udid

DesiredCapabilities capabilities = new DesiredCapabilities(); 
capabilities.setCapability("device","Android");
capabilities.setCapability("deviceName", "b1d12c6");
capabilities.setCapability("udid", "b1d12c6");
capabilities.setCapability("platformVersion", "4.4.4");
capabilities.setCapability("platformName", "Android");
capabilities.setCapability("appPackage", "com.runmit.sweedee");
capabilities.setCapability("appActivity", "com.runmit.sweedee.LoadingActivity");
driver = new AndroidDriver(new URL("http://127.0.0.1:4723/wd/hub"), capabilities);

DesiredCapabilities capabilities2 = new DesiredCapabilities();
capabilities2.setCapability("device","Android");
capabilities2.setCapability("deviceName", "0123456789ABCDEF");
capabilities2.setCapability("udid", "0123456789ABCDEF");
capabilities2.setCapability("platformVersion", "4.4.4");
capabilities2.setCapability("platformName", "Android");
capabilities2.setCapability("appPackage", "com.runmit.sweedee");
capabilities2.setCapability("appActivity", "com.runmit.sweedee.LoadingActivity");
driver2 = new AndroidDriver(new URL("http://127.0.0.1:4725/wd/hub"), capabilities2);

之后同时启动成功

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 44 条回复 时间 点赞

adb 每次默认的是第一个识别到的devices,

剪烛 #2 · July 02, 2015 作者

#1楼 @testly 那写devicename感觉没什么意义啊~~(╯﹏╰)b
那么用一个ios设备感觉会没问题?

#2楼 @shixue33 ios的话Xcode 本身就只能调试一个设备,

剪烛 #4 · July 02, 2015 作者

#3楼 @testly 嗯嗯,我意思是如果是mac上接一台安卓设备,一台iOS设备的话

#2楼 @shixue33 有个想法,可以利用docker开N个container ,每个container connect一个 IP端口 adb 通过WiFi映射 脱离数据线 无线控制多台手机!

剪烛 #6 · July 02, 2015 作者

#5楼 @testly ! 可以尝试下(・ิϖ・ิ)っ

可以这么做:
1、Appium Server启动的时候分别指定好UDID、Port(主要是AppiumPort、bootStrapPort)
2、脚本里session别起两个了,用例这样参在一起容易出问题的,用例就按照suite或者类区分开来
3、同时执行两个testSuite,就不冲突了

appium/lib/devices/android/android-common.js

if (this.adb.udid) {
if (!_.contains(_.pluck(devices, 'udid'), this.adb.udid)) {
return cb(new Error("Device " + this.adb.udid + " was not in the list " +
"of connected devices"));
}
deviceId = this.adb.udid;
}

android 上 deviceName 确实没啥用,要指定设备需要用 udid 。

这个文档也有说明:
https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/caps.md

剪烛 #9 · July 03, 2015 作者

#8楼 @chenhengjie123 #7楼 @anikikun #5楼 @testly
3q ~已经解决~
capabilities中设置udid后,可以同时启动两台测试设备

剪烛 #10 · July 03, 2015 作者

#7楼 @anikikun 我估计分开写不太好写。我先尝试下。

capabilities中配置udid或者appium启动的时候,带-U udid -port 端口,两种方式能解决一台PC控制多台终端问题;从Appium服务代码来看,Appium是根据用户是否在capabilities配置了udid,如果配置了,则直接pick 这台device,如果没有配置,则pick第一台设备,片源如下:

官网针对多机执行解释如下:

#9楼 @shixue33 很赞啊~联动测试的解决方案那么就有了。
这样一来,两个用户互相收发消息的用例都可以很还原得做了。

两个设备交互写到两个 suit 挺麻烦的,交互能分开测吗,变成
iPhone --> fake server
fake client --> 盒子

很好呀~~~

剪烛 #15 · July 03, 2015 作者

#13楼 @sanlengjingvv 我觉得让我自己去拼装json数据,真的还挺麻烦的。json数据复杂,
如果有工具能将http请求录制下来,可能会好点

不需要拼装json

剪烛 #17 · July 03, 2015 作者

#16楼 @a00ium 那怎么操作呢?

看了那么多帖子了 看来做出来的人是不愿意分享出来的 还有人说已经跑了半年了。。+@shixue33

剪烛 #19 · July 03, 2015 作者

#18楼 @a00ium ⊙﹏⊙!!!

pls check email @shixue33

#9楼 @shixue33 怎么解决的呢,刚接触呢,求指教,也想同时启动两台测试设备

@shixue33 同求解决方案,没有思路

@shixue33 楼主,这个问题怎么解决的,告诉下思路

用appium 在同一台电脑上启动了两个 server,分别用两台实体机去链接不同的server,发现拿到的sessionId 却是一致的,这个怎么处理?

#24楼 @ji_an_ke 你把日志贴出来看一下

#22楼 @xuanjian 分别设置udid就好了

求问,我根据你的代码写的然后还是出问题了,就运行到这里一只下不去

#27楼 @litost 官方群找下我(剪烛),你提供的信息不全,我帮你排查下

官方群没理我没理我,加不进来,我的qq1369449700

#25楼 @shixue33 最终解决了,自己太粗心

剪烛 [Topic was deleted] 中提及了此贴 14 Nov 21:58

我想问下,这边的udid是adb devices命令查看到的第一列的那一串数字吗?之前写了程序获取udid=7d93c668-d2d2-32eb-826f-e3eadeeedb36,结果appium报找不到设备

剪烛 #34 · December 20, 2016 作者

#33楼 @mona0505 不太像Android的啊……Android的一般没这么长,你这是iOS的设备么?

adb devices
List of devices attached
c146cbc5 device

#34楼 @shixue33 所以这边指定的udid就是通过adb devices看到的第一列的那一串咯?咦~~~

#34楼 @shixue33 不是IMEI或者IMSI之类的?

#37楼 @shixue33 好的,谢谢!

太好了,解决了我的问题,nice

按照这个方法,确实能启动两台机器了,但是却只在一台机器上执行了用例,这是为什么呢?

剪烛 #41 · March 13, 2017 作者
zenghuan 回复

介不介意把代码贴上来看下呢?

Mr_C 回复

想请问下,你这个情况最后怎么解决的?目前我也遇到这个问题了

剪烛 #43 · March 27, 2017 作者
丫丫 回复

你好,分别指定udid就可以解决,如果需要完全并行,在脚本使用两个线程就可以了

剪烛 回复

真的吗!

剪烛 #45 · March 27, 2017 作者
回复

吓得我马上去试一下

剪烛 回复

在脚本使用两个线程是什么意思?

需要 Sign In 后方可回复, 如果你还没有账号请点击这里 Sign Up