ATX ATX 文档 - iOS 控件操作 API

codeskyblue · 2017年01月21日 · 最后由 codeskyblue 回复于 2019年10月12日 · 8102 次阅读
本帖已被设为精华帖!

补充说明

部分接口已经过期,请参考最新的文档 https://testerhome.com/topics/9854

前言

这天万里无云,PM 指数 50 以下,正式写文章的好日子。ATX 群里一直都有人说需要一篇 iOS 操作的接口列表,被我拖延到了现在,快过年了,坚决不能拖延到年后。
接口手册按照我以前的风格肯定是写到 Github 的 README 里面的,但是这样有个坏处,就是看不到浏览数,也没法评论,修改起来也不是很方便。最头疼的是贴图不方便。所以最终决定把接口手册放到 Testerhome 上,一来可以帮 testerhome 导入点流量,另外该要的功能也都有了。

为了方便快速书写,用到了一些简称。比如 ATX 代表 AutomatorX,WDA 代表 WebDriverAgent

环境搭建部分可以独立成章,但文章我不想主要介绍这个,所以都只是简单的提了下,通过提到的线索你依然可以搭建起来环境。
主要部分还是介绍接口,而且接口会根据 Github 上的代码变更随时更新。

环境准备

  • Mac 电脑
  • iPhone 手机(实在没有,用模拟器也行)
  • WebDriverAgent 首页有说明,把他运行起来就好。
  • Python(这个要会用)目前 ATX 兼容 py2.7,理论上兼容 py3.4 但是还没测试过
  • AutomatorX

    ATX(AutomatorX 的简称)的安装不看文档也可以,反正也不难,两个命令就装好了

    pip install --pre --upgrade atx
    pip install opencv_python
    

接口列表

为了方便调用 WDA,于是写了一个纯 Python 的 WDA 客户端facebook-wda,如果有些接口下面的文章没有提到,在该项目的 README,或者代码中或许可以发现一些彩蛋。

连接设备

如果连接的是真机的话,还需要通过 iproxy 将手机监听的 8100 端口转发到本地来。

这里假设你启动的 WDA 的地址是http://localhost:8100

import atx

d = atx.connect("http://localhost:8100")

后面的接口都会默认你已经有d这个变量了

应用的启停

需要知道应用的 bundleId,可以通过ideviceinstaller -l查到。

d.start_app('com.apple.Health') # 启动默认的健康程序
d.stop_app()

基本操作

屏幕大小,这里是实际显示的大小。截图是多大,返回的就是多大

dis = d.display
print dis.width, dis.height

截图

image = d.screenshot() # 返回PIL图片
image.save("screen.png") # 保存成文件,这个是PIL的基础用法。其他的什么旋转,抠图,还有很多

坐标点击

d.click(20, 30)

滑动

d.swipe(300, 400, 300, 100, 1.0) # 从(300, 400)滑动到 (300, 100) 时间1.0s (默认0.2s)

其他

d.home() # 点击Home键

选择控件

浏览器打开 WDA 的 inspector 窗口

右上角的用户图标,我们可以根据 Class,Name,Label 来定位

# 根据所有属性定位
elem = d(class_name="Button", name="profile", label="profile")
# 使用下标定位,界面上的第2个Button(下标是从0开始的)
elem = d(class_name="Button", index=1)
elem = d(class_name="Button")[1] # 跟上面的命令等价

通过 xpath 定位

xpath 有很多的规则,我用的很少,欢迎高手留言补充。这种操作比较慢,但是功能强大

elem = d(xpath="//Button")

控件操作

elem.exists # 判断控件是否存在
len(elem) # 返回符合条件元素的个数

elem.click() # 等待并点击
elem.click(timeout=5.0) # 5s之内还有出现符合条件的元素,直接跑异常。timeout目前默认都是90s
elem.wait(timeout=5) # 等待目标的出现
elem.tap_hold(2) # 长按2s

# elem.swipe('up') # 这个接口目前没有了,有待更新

elem.bounds # 返回namedtuple,这个坐标体系还需要乘以 d.scale 才能转化成ATX的坐标体系。
# Returns
# Rect(x=279, y=29, width=25, height=25)

# 获取元素的属性
elem.class_name
elem.text # 这个跟inspector中的Name一个意思
elem.value
elem.enabled # 是否启用
elem.displayed # 这个还真的很少用

刚才的应用进入到用户界面,点击 Edit,会进入到这个界面,正好可以演示下怎么输入这个功能

用 inspector 可以看到元素的结构是这个样子的

输入框

为了确保不被所谓的联想字符,自动修正所干扰,打开输入法设置界面,将所谓的联想输入都关闭掉。
是否支持中文呢?刚试了下,竟然支持(自己都觉得惊讶)

为了找到输入框,不得不用复杂的 xpath 了,xpath 的使用我参考了这篇文章http://www.cnblogs.com/songshu120/p/5182043.html

elem = d(xpath="//Cell[@label='First Name']/TextField")
elem.set_text("James") # 设置文本
elem.value # 获取刚刚输入的文本
elem.clear_text() # 清空刚刚输入的文本

除了这种方法还有另外一种方法

elem.click() # 使输入框处于激活状态
d.type("James")
d.type("\b\b") # 删除两个字符

Scroll

s(text="Vitals").scroll() # scroll to visible
s(text="Login").scroll().click() # 滑到到该元素,然后点击
s(text="Hello").scroll(direction="right", timeout=5.0) # 指定滑动的方向向右,方向有4个up | down | left | right
# 有点尴尬了,我也不记得下面两个是干什么用的了
s(text="Hello").scroll(text="World")
s(text="Hello").scroll(text_contains="World")

警告框

目前封装的一般般,但也可以酬和着用

d.session.alert.text # 当前弹出框的文本
d.session.alert.accept() # 点击弹出框的确认
d.session.alert.dismiss() # 点击弹出框的取消

DONE

真是多呀,写了这么久。不幸的是还是没有写完。ATX 还有图像识别这一块,篇幅差不多也可以写跟这篇一样多了。先写这么多吧,累死我了,打游戏去了。

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

辛苦辛苦!

👍 👍 👍 👍 👍 明年我正好要写接口,给我点启示,非常谢谢,

我看这定位控件/操作控件这套东西,怎么感觉不像是接口自动化呢?接口自动化不是应该脱离 UI 层吗?个人愚见

标题写歧义了,开始我也误解了。
这是 ATX 的 API 说明文档。

#5 楼 @among29 稍等,我改下

辛苦,辛苦!
👏

retry to connect, error: HTTPConnectionPool(host='127.0.0.1', port=8100): Read timed out. (read timeout=10). 麻烦问一下这个操作超时时间如何设置更改

#8 楼 @yundanfengqing007 你操作什么了?

#8 楼 @yundanfengqing007 你执行了什么操作,怎么会超时

写了一个循环依次点击 button[1~5],点到第三个 button 时就会超时,前 2 个可以正常点击。如果只点击第 3 个 button 也是正常的。好诡异,不过前 2 个 button 点击速度也是挺慢的

#11 楼 @yundanfengqing007 打开调试,可以查看下执行了哪些 HTTP 请求。估计还是 WDA 出了啥问题

import wda

wda.DEBUG = True

@codeskyblue 你好楼主,我想问下你这个 ATX 能否支持 webview 中的页面元素获取,我看你这个 demo 基本都是 native 的

能并发么?

#16 楼 @sixleaves 理论上没问题,我只试过同时开模拟器和手机

#17 楼 @codeskyblue 我发现多机器 (指手机) 直接并行编译 WDA 会有问题,不知道你怎么解决的~

#19 楼 @codeskyblue 😂 我说的就是命令行啊,xcodebuild 那条命令

恒温 将本帖设为了精华贴 02月14日 08:37

更加期待 ATX 在游戏测试方面的实践

#22 楼 @Lihuazhang 很不幸的是,内部推广的也一般,所以没多少实践可以分享的

#24 楼 @Lihuazhang 如今的情况是社区的活跃度要大于内部的

恒温 回复

最近也在看游戏自动化测试方面的,看了腾讯的 GA 方案,但不支持 iOS,还有网易的这个 AutomatorX(基于 OpenCV, 和 Google 2015 在 GTA 上分享的方案一样),不知道还有其他可用的第三方么?

codeskyblue 回复

这个 webview 也适合 ios 么

sixleaves 回复

前段时间听说 sikuli 支持移动端了,不知道是不是支持 iOS

jmei 回复

还没封装进来,但是最终也只是简单的封装 selenium。Android 的 webview 已经集成进来了

codeskyblue 回复

不支持真机,貌似是支持模拟器。

codefarmer ATX 文档 - iOS WebDriverAgent 环境搭建 入门 中提及了此贴 03月09日 11:59
32楼 已删除
codeskyblue 回复

你好,我在多真机运行几十条测试用例的过程中,时不时碰到 http 连接断掉的情况,有什么办法监控 wda 的状态么,想断掉就自动重启 wda

jmei 回复

命令行启动,失败了会自动退出的

比如 live photo,我想长按,要怎么实现。
API 操作的有更详细的文档吗

loneyao 回复

d.session.tap_hold(x, y, duration=1) 这种方法,一些没有提到的方法可以在这里找到
https://github.com/openatx/facebook-wda

codeskyblue 回复

好的,谢谢了。

翔哥😀 😀 😀

cg 回复

谁呀

codeskyblue 回复

现在 atx 支持 ios 的 webview 测试了么,求分享经验

jmei 回复

目前还没有集成到 ATX 中

codeskyblue ATX 资料快速索引 中提及了此贴 06月21日 19:39

环境:python3.6

代码如下

import atx

d = atx.connect("http://localhost:8100")
d.start_app(bundleId)

我在调用 start_app(bundleId) 时,报下面的错误,请问有遇到过着种情况吗:

  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/atx/drivers/ios_webdriveragent.py", line 74, in start_app
    self._session = self._wda.session(bundle_id)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/wda/__init__.py", line 207, in session
    res = self._request('session', 'POST', data=data)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/wda/__init__.py", line 143, in _request
    return httpdo(urljoin(self._target, base_url), method, data)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/wda/__init__.py", line 75, in httpdo
    response = fn(url, data=data, timeout=10)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/requests/api.py", line 112, in post
    return request('post', url, data=data, json=json, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/requests/api.py", line 58, in request
    return session.request(method=method, url=url, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/requests/sessions.py", line 508, in request
    resp = self.send(prep, **send_kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/requests/sessions.py", line 618, in send
    r = adapter.send(request, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/requests/adapters.py", line 490, in send
    raise ConnectionError(err, request=request)
requests.exceptions.ConnectionError: ('Connection aborted.', RemoteDisconnected('Remote end closed connection without response',))
'''
meitian 回复

你这个问题解决了吗?如何解决的呢

雨雾恨 回复

没解决,现在没有在用 atx

请问这个操作支持 ios10 以上的系统吗??

何畅 回复

有人试过支持 ios11 的

执行速度怎么样? 应该比 appium 快吧

wolfgao 移动客户端 /UI 开源测试框架梳理和大比拼 中提及了此贴 02月27日 21:03

用 WDA 的 inspector 去抓界面元素,不会很慢吗?

lang.feng 回复

会呀

codeskyblue 回复

那你还是用这个抓界面吗?我这有时一直刷新状态刷不出来,醉了,请问你有更好的办法吗?

codeskyblue 回复

IOS 的 H5 页面现在也支持了吗

想问一下 atx 可以模拟 ctrl+v 操作吗?比如我在页面点击一个按钮 ‘复制链接’,怎么如何把复制的链接赋值给一个变量,或者保存本地

边万成 回复

有这个接口,但貌似不太好使

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册