导语

一直在强调WebDriverAgent作为server端,通过USB和手机进行通信,那么client如何触发点击的呢?正好通过xpath定位方式的编写,可以让我们熟悉这个流程。
借助wda可以实现定位和跨应用,仔细看了wda的api,发现缺少xpath定位的方式,再到WebDriverAgent源码可以看到,有xpath的定位api,决定给wda添加xpath定位方式。


一、开始

先查看api,可以参考WebDriverAgent(二)
或者直接进入WebDriverAgent Wiki
确认xpath api,然后开始动手。

二、mac终端curl命令

第一步:需要先手动启动xcode schemes,选择WebDriverAgentRunner,Test启动
WebDriverAgent以后。手动启动app应用。
第二步:获取session id
终端命令行输入

1
curl -X GET -H "Content-Type: application/json" http://192.168.1.101:8100/source

返回值的最后可以看到sessionId,作为下一步xpath使用。
第三步:调用xpath api
终端命令行输入

1
2
3
4
curl -X POST -H "Content-Type: application/json" \-d "{\"using
\":\"xpath\",\"value\":\"//XCUIElementTypeCell[1]/
XCUIElementTypeStaticText\"}" \http://192.168.1.101:8100/
session/sessionId/elements

返回值是一个字典形式:可以看到status为0,且有value不为空。这里的status为0代表是正常的请求。
可以看到请求成功了

三、用python实现请求

wda作者封装了nameclassname定位,很简单直接在方法里添加,最初思路考虑到使用
wda用户的使用xpath定位的习惯,有两种形式:

1
2
(1)//Button/Cell[@name='1111']
(2)//*/Button/Cell/Button/Cell

1、直接使用replace替换

1
2
3
4
5
6
7
8
9
if xpath and not xpath.startswith('//XCUIElementType'):
if not xpath.startswith('//'):
self._xpath = '//'+('XCUIElementType'+xpath).replace('/', '/
XCUIElementType')
elif xpath.startswith('//*'):
self._xpath = '//*'+('XCUIElementType'+xpath[3:]).replace('/','/
XCUIElementType')
elif xpath.startswith('//'):
self._xpath = '/'+xpath[1:].replace('/','/XCUIElementType')

代码显得凌乱,可读性差。

2、决定修改

1
2
3
4
5
6
7
8
9
10
11
if xpath and not xpath.startswith('//XCUIElementType'):
if xpath.startswith('//*'):
xpath = xpath[3:]
else:
if xpath.startswith('//'):
xpath = xpath[2:]
elif xpath.startswith('/'):
xpath = xpath[1:]
xpath = re.split('/', xpath)
self._xpath = '//XCUIElementType'+('/XCUIElementType'.join(xpath))

开源作者提意见是不希望有判断(if else)存在

3、用正则

1
2
3
if xpath and not xpath.startswith('//XCUIElementType'):
element = '|'.join(xcui_element_types.xcui_element)
self._xpath = re.sub(r'/('+element+')', '/XCUIElementType\g<1>', xpath)

看了官方源码有iOS控件库,把所有可能的控件形式穷举出来,然后用sub匹配替换。
终于完成,提交给开源作者审核

To be continued soon……