使用 WebDriverAgent/XCTest Backend 进行iOS自动化手势操作


使用 WebDriverAgent/XCTest Backend 进行iOS自动化手势操作

很可惜,苹果官方的 XCTest 框架本身并不支持 TouchAction 接口实现的 W3C 标准。尽管如此,XCTest 提供了非常丰富的手势操作,这些操作都是 iOS 平台独有的。你可以在 1.6.4-beta 版本的 Appium 中开始使用这些手势操作。

需要特别注意的是目前XCTest和WDA正在不断优化改变的阶段,这意味着所有 mobile: * 的命令可能会在没任何通知的情况下就被调整更改。

mobile: swipe

这个手势是在指定的屏幕上的控件或App的控件上执行“滑动”操作,一般是针对整个屏幕。这个方法不支持通过坐标来操作,并且仅仅是简单的模拟单个手指滑动。这个方法对于诸如相册分页、切换视图等情况可能会发挥比较大的作用。更复杂的场景可能需要用到mobile:dragFromToForDuration,这个方法支持传坐标(coordinates )和滑动持续时间(duration)。

支持参数

  • direction: 'up', 'down', 'left' or 'right'. 这4个参数是固定的。
  • element: 需要滑动的控件ID(作为十六进制哈希字符串)。如果没有提供该参数的话,则会使用App的控件作为替代。

用法示例

// Java
JavascriptExecutor js = (JavascriptExecutor) driver;
Map<String, Object> params = new HashMap<>();
scrollObject.put("direction", "down");
scrollObject.put("element", ((RemoteWebElement) element).getId());
js.executeScript("mobile: swipe", params);

mobile: scroll

滚动元素或整个屏幕。支持不同的滚动策略。该方法提供了4个可选择滑动策略:按照顺序有“name”,“direction”,“predicateString”或“toVisible”。所有的滑动策略都是排他性的,一次滑动只能选择一个策略。你可以使用mobile:scroll来对表格中或者集合视图中的某个已知控件进行精确的滚动操作。然而目前有一个已知的局限问题:如果需要在父容器上执行太多的滚动手势来达到必要的子元素(其中几十个),则方法调用可能会失败。

支持参数

  • element: 需要滚动的控件ID(作为十六进制哈希字符串)。如果没有提供该参数的话,则会使用App的控件作为替代。
  • name: 需要执行滚动的子控件的accessibility id。 将predicateString参数设置为“name == accessibilityId”可以实现相同的结果。如果element不是容器,则不起作用。
  • direction: 'up', 'down', 'left' or 'right'. 该参数与swipe中的比,差别在于scroll会尝试将当前界面完全移动到下一页。(page一词表示单个设备屏幕中的所有内容)
  • predicateString: 需要被执行滚动操作的子控件的NSPredicate定位器。如果控件不是容器,则不起作用。
  • toVisible: 布尔类型的参数。如果设置为true,则表示要求滚动到父控件中的第一个可见到的子控件。如果element未设置,则不生效。

用法示例

# Python
driver.execute_script('mobile: scroll', {'direction': 'down'});

mobile: pinch

在给定的控件或应用程序控件上执行捏合手势。

支持参数

  • element: 需要捏合的控件ID(作为十六进制哈希字符串)。如果没有提供该参数的话,则会使用App的控件作为替代。
  • scale: 浮动型夹点尺度。使用0和1之间的比例来“捏紧”或缩小,大于1的比例“撑开”或放大。强制参数
  • velocity: 每秒缩放速度(浮点值)。强制参数

用法示例

# Ruby
execute_script 'mobile: pinch', scale: 0.5, velocity: 1.1, element: element.ref

mobile: doubleTap

在指定控件上或屏幕上执行双击手势。

支持参数

  • element: 需要双击的控件ID(作为十六进制哈希字符串)。如果没有提供该参数的话,则会使用App的控件作为替代。
  • x: 屏幕x轴坐标点,浮点型. 仅当element未设置时才是强制参数
  • y: 屏幕y轴坐标点,浮点型. 仅当element未设置时才是强制参数

用法示例

// javascript
driver.execute('mobile: doubleTap', {element: element.value.ELEMENT});

mobile: touchAndHold

在指定控件上或屏幕上长按的手势操作。

支持参数

  • element: 需要长按的控件ID(作为十六进制哈希字符串)。如果没有提供该参数的话,则会使用App的控件作为替代。
  • duration: 长按的持续时间(秒),浮点型。强制性参数
  • x: 屏幕x轴坐标点,浮点型. 仅当element未设置时才是强制参数
  • y: 屏幕y轴坐标点,浮点型. 仅当element未设置时才是强制参数

用法示例

// c#
Dictionary<string, object> tfLongTap = new Dictionary<string, object>();
tfLongTap.Add("element", element.Id);
tfLongTap.Add("duration", 2.0);
((IJavaScriptExecutor)driver).ExecuteScript("mobile: touchAndHold", tfLongTap);

mobile: twoFingerTap

在给定元素或应用程序元素上执行两个手指点击手势。

支持参数

  • element: 需要两只手指操作的控件ID(作为十六进制哈希字符串)。如果没有提供该参数的话,则会使用App的控件作为替代。

用法示例

// c#
Dictionary<string, object> tfTap = new Dictionary<string, object>();
tfTap.Add("element", element.Id);
((IJavaScriptExecutor)driver).ExecuteScript("mobile: twoFingerTap", tfTap);

mobile: tap

在指定控件或屏幕上的坐标执行点击手势。

支持参数

  • element: 控件ID(作为十六进制哈希字符串)。 如果设置 了element参数,则xy代表的是以当前element为边界的xy轴。若未设置,则x,y代表的是以手机屏幕为边界。
  • x: x轴坐标,类型为float。强制参数
  • y: y轴坐标,类型为float。强制参数

案例

// PHP
$params = array(array('x' => 100.0, 'y' => 50.0, 'element' => element.GetAttribute("id")));
$driver->executeScript("mobile: tap", $params);

mobile: dragFromToForDuration

通过坐标点执行拖放手势。可以在控件上执行,也可以在屏幕上执行。

Supported arguments

  • element: 控件ID(作为十六进制哈希字符串)。 如果设置 了element参数,则xy代表的是以当前element为边界的xy轴。若未设置,则x,y代表的是以手机屏幕为边界。
  • duration: 浮点数范围[0.5,60]。表示开始拖动点之前的点击手势需要多长时间才能开始拖动。强制参数
  • fromX: 起始拖动点的x坐标(类型float)。强制参数
  • fromY: 起始拖动点的y坐标(类型float)。强制参数
  • toX: 结束拖曳点的x坐标(float类型)。强制参数
  • toY: 结束拖动点的y坐标(类型float)。强制参数

用法示例

// Java
JavascriptExecutor js = (JavascriptExecutor) driver;
Map<String, Object> params = new HashMap<>();
params.put("duration", 1.0);
params.put("fromX", 100);
params.put("fromY", 100);
params.put("toX", 200);
params.put("toY", 200);
params.put("element", ((RemoteWebElement) element).getId());
js.executeScript("mobile: dragFromToForDuration", params);

mobile: selectPickerWheelValue

选择下一个或上一个picker wheel的值。 如果这些值是动态的,那么这个方法是能起作用的。XCTest有一个BUG就是你并不能知道要选择哪一个或者当前的选择区域是否生效。

支持参数

  • element: PickerWheel的内部元素id(作为十六进制哈希字符串)执行值选择。元素必须是XCUIElementTypePickerWheel类型。强制参数
  • order: next 选择下一个value,previous选择前面一个value。强制参数
  • offset: 区间值: [0.01, 0.5]。它定义了picker wheel的中心距离应该有多远。 通过将该值乘以实际的picker wheel高度来确定实际距离。太小的偏移值可能不会改变picker wheel的值,而过高的值可能会导致picker wheel同时切换两个或多个值。通常最优值位于范围[0.15,0.3]中。默认为0.2

用法示例

// Java
JavascriptExecutor js = (JavascriptExecutor) driver;
Map<String, Object> params = new HashMap<>();
params.put("order", "next");
params.put("offset", 0.15);
params.put("element", ((RemoteWebElement) element).getId());
js.executeScript("mobile: selectPickerWheelValue", params);

mobile: alert

对NSAlert实例执行操作。

支持参数

  • action: 支持以下操作: accept, dismiss and getButtons。强制参数
  • buttonLabel: 点击已有警报按钮的标签文本。这是一个可选参数,只能与acceptdismiss 操作相结合才有效。

用法示例

# Python
driver.execute_script('mobile: alert', {'action': 'accept', 'buttonLabel': 'My Cool Alert Button'});

进阶主题

查看 WDA Element Commands API 以获取有关在Facebook WebDriverAgent中实现的手势的信息。