Appium [求助] Appium 在 iOS 上怎么实现多设备操作

少陵生 · April 08, 2016 · Last by 小小的蜗牛 replied at February 09, 2020 · 5416 hits

一直使用Appium + Robot Framework做自动化测试,之前在Android设备上,可以通过Switch Application方法切换不同设备。现在在iOS真机上,可以同时在不同设备上打开App,但是想做切换的时候,一直会遇到问题,Appium Server也没用什么有效的Log。

官方文档在iOS多设备测试的时候说得很含糊,只说因为simulator的限制,没说真机的情况。
Unfortunately, running local parallel iOS tests aren’t possible. Unlike Android, only one version of the iOS simulator can be launched at a time, making it run multiple tests at once.
If you do want to run parallel iOS tests, you need to use Sauce. Simply upload your Appium test to Sauce, and it can run as many parallel iOS or Android tests as your account allows. See more about running your tests on Sauce here.n

不知道有没有在这方面有经验的,或者提供一些建议也行。

共收到 32 条回复 时间 点赞

用多个苹果机器

#1楼 @lihuazhang 多个苹果机器,是指多个Mac么?

4Floor has been deleted

#4楼 @nostop 就是这样啊,多台苹果电脑组成grid ,没人再说幽默

#5楼 @lihuazhang 试了,还真的可以…… 不知道为什么一个mac就不行

#5楼 @lihuazhang 没有使用grid,直接在capability里面制定不同ip的Appium server,switch操作就没问题了

#6楼 @shljsh instruments 没法多线程

#4楼 @nostop 哪儿污了。。。= =

我们在移动端做一个可以远程遥控的agentAPP来调用instrumentation执行自动化。电脑就可以做到多线程来控制了

一台mac机交替运行多台设备可用如下方法,必须指定下tmp参数才可行
appium -p 4727 --tmp /tmp/tmp4727
appium -p 4729 --tmp /tmp/tmp4729
并发运行ios目前还不支持

少陵生 #12 · May 24, 2016 作者

#11楼 @greenplum 能够交替运行就解决我的需求了 非常感谢

如果是Java的话,Appium可以结合TestNG使得一部Mac机器连接多部iOS设备实现test case parallel运行,甚至可以实现test case distribute运行

greenplum 回复

并发运行ios目前还不支持

请问Appium暂时还不能并发运行多台iOS设备吗?

Anson 回复

我想尝试使用TestNG.xml传参实现调配多设备并行运行,但是目前并没有很多关于这方面的博文

传参失败!!

请问你有做过这方面的尝试吗?

sini 回复

iOS可以多个设备同时执行,但是不支持多个模拟器。传参失败把具体原因写出来把,这个没有难点,多线程或者并发都可以简单实现。

少陵生 回复

TestNG.xml 文件配置

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="suite" parallel="classes" thread-count="3">
<test verbose="2" name="Sales">
<parameter name="port" value="4788"/>
<parameter name="udid" value="9da82887884423f91840e4a4601862d2821de94a"/>
<classes>
<class name="rl.ipos.cucumberTest.CheckStoreCukesTest"/>
</classes>
</test>
<test verbose="2" name="CustomerManage">
<parameter name="port" value="4777"/>
<parameter name="udid" value="2600ede04135ffc36df6c6e57cf2b4ad34c52f96"/>
<classes>
<class name="rl.ipos.cucumberTest.OpenShopCukesTest"/>
</classes>
</test>
</suite>

iosDriver 初始化

public class Driver {
private int port;
private String udid;

protected static IOSDriver<IOSElement> iosDriver;
protected static AppiumDriverLocalService service;

@BeforeTest
@Parameters({"port", "udid"})
public void setPortUDID(int port, String udid) {
this.port = port;
this.udid = udid;
System.out.println("\nport:" + port + ",udid:" + udid + "\n");
}

private int getPort() {
return this.port;
}

private void setPort(int port) {
this.port = port;
}

private void setUdid(String udid) {
this.udid = udid;
}

private String getUdid() {
return this.udid;
}

public static AppiumDriver getDriver() {

Driver driver = null;

if (iosDriver == null) {
// File file = new File(IPOSConfigPath.DRIVER_CONFIG_FILE);
// ObjectMapper objectMapper = new ObjectMapper();
//
// try {
// driver = objectMapper.readValue(file, Driver.class);
//
// } catch (IOException e) {
// System.out.println("配置文件错误");
// }

AppiumServiceBuilder builder = new AppiumServiceBuilder();
builder.usingAnyFreePort();
builder.withIPAddress("127.0.0.1");
service = AppiumDriverLocalService.buildService(builder);

service.start();

if (service == null || !service.isRunning()) {
throw new AppiumServerHasNotBeenStartedLocallyException("An appium server node is not started!");
}

File appDir = new File(System.getProperty("user.dir"), "/apps/");
File app = new File(appDir, "rlterm3.app");
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability(MobileCapabilityType.BROWSER_NAME, "");
capabilities.setCapability(MobileCapabilityType.PLATFORM_VERSION, "10.3.0");
capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "autotest");
capabilities.setCapability(MobileCapabilityType.UDID, driver.getUdid());
capabilities.setCapability(IOSMobileCapabilityType.LAUNCH_TIMEOUT, 500000);
capabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME, AutomationName.IOS_XCUI_TEST);
capabilities.setCapability(MobileCapabilityType.APP, app.getAbsolutePath());
capabilities.setCapability(MobileCapabilityType.NO_RESET, true);
capabilities.setCapability("useNewWDA", true);
iosDriver = new IOSDriver<>(service.getUrl(), capabilities);
//每次Driver执行 找不到元素都会等待此处设置的时间
iosDriver.manage().timeouts().implicitlyWait(480, TimeUnit.SECONDS);
//如果在加载时间还不能加载完页面那会抛出超时异常
// iosDriver.manage().timeouts().pageLoadTimeout(15, TimeUnit.SECONDS);

}
return iosDriver;
}
}

Appium+cucumber

测试启动时,通过cucumber找到对应步骤,每一步骤实例化driver

protected AppiumDriver driver = Driver.getDriver();
在这里实例化的时候报driver类这行代码空指针
capabilities.setCapability(MobileCapabilityType.UDID, driver.getUdid());

也就是说这个udid值并没有上传成功

sini 回复

看xml文件里面配置了3个线程,但是只有2个套设备的信息,这块会有问题。
设置为class级别的并发,2个线程只会执行一遍beforetest方法,建议把setPortUDID这个方法放到beforemethod里面做。
另外把port这类参数当成Driver的内部变量,线程之间不够安全,可能会互相有冲突。建议把port这个搞成list,然后在执行case的时候,根据case所在线程的名字或者序号去取到不同的线程。

少陵生 回复

这种通过testng.xml文件传参,是不是就需要使用Selenium Grid

我一直很混乱这两个方式,这两个是作为一个方式一起使用,还是可单独使用的呢?

sini 回复

两码事,使用Selenium Grid就是可以让appium和设备不在跑脚本的计算上

少陵生 回复

谢谢,明白了

初始化时port使用的是builder.usingAnyFreePort();任意自由port应该没有关系,关键是udid这个参数并没有通过TestNG.xml传过来
可能在某个环节还是出了点儿问题

sini 回复

建议自己发现连接本地电脑的设备,然后自动获取udid

少陵生 回复

这个应该如何实施呢?

sini 回复

java脚本调用"idevice_id -l"命令去查询

sini 回复

请参考testng的parameter传参文档
http://testng.org/doc/documentation-main.html#parameters-testng-xml

如有可能,尽量不要用testng.xml这种写死的方法,用testng的virtual testng.xml,
http://testng.org/doc/documentation-main.html#running-testng-programmatically
此方法,对付selenium,多浏览器支持,多浏览器并发,不同test case不同浏览器(如TC1跑chrome, firefox, safari,TC2跑edge, chrom, firefox)绰绰有余,再加上Java的annotation,分类跑test case,如(@Smoke@BVT等)这样的分组也是绰绰有余,当然,testng本身是支持group的,不用annotation也行。

然后照搬到appium上面就行了。

少陵生 回复

xcode 9支持多simulator运行。

sini 回复

使用

builder.usingAnyFreePort();

怎么在运行时把port传到写死的testng.xml里面去?
按照正常流程,初始化appium的ios instance是在testng.xml更新动作之后,更新testng.xml因为是在testng介入之前,然后,初始化appium已经是testng整个初始化完成了,开始跑测试了,肯定无法更新testng.xml,再让testng再次读取新的testng.xml。

Anson 回复

谢谢你的建议,我尝试一下

少陵生 回复

我用的是Appium+python,Mac 开启了多个端口的appium server,但是链接俩设备后,不管desired_caps怎么指定udid,都只能调起其中一台设备(最近使用过的那台),这是什么原因呢?

木头 回复

你启动appium server的时候可能要多加一个uiautomator的端口参数

木头 回复

我也是同样的问题

木头 回复

因为driver被覆盖了。

Arvinting 回复

麻烦问下你的问题解决了吗

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