Appium WebDriverAgent 不支持数字键盘 sendkeys 的解决方法

adfghzhang · 2017年03月09日 · 最后由 雨雾恨 回复于 2017年10月16日 · 3038 次阅读

最近弄 iOS 的自动化测试时发现 appium 和 macaca 均不能在数字键盘弹出时进行 clear 和 sendkeys 操作,想来应该是 WDA 的问题了。问题描述见https://github.com/appium/appium/issues/8004

该方法适用于 macaca 和 appium 以及其他使用 WDA 做底层驱动的测试框架(根据各框架的 API 进行改动即可😺)。

一、 分析数字键盘

规律如下,数字 1-9 对应的 xpath 为:
/XCUIElementTypeApplication/XCUIElementTypeWindow[4]/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther[2]/XCUIElementTypeButton[1-9]
数字 0 对应:
/XCUIElementTypeApplication/XCUIElementTypeWindow[4]/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther[2]/XCUIElementTypeButton[11]
Done/完成按钮对应:
/XCUIElementTypeApplication/XCUIElementTypeWindow[4]/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther[2]/XCUIElementTypeButton[10]
X 删除按钮对应:
/XCUIElementTypeApplication/XCUIElementTypeWindow[4]/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther[2]/XCUIElementTypeButton[12]

二、 分析全键盘


全键盘弹出时能正常识别,控件类型为 XCUIElementTypeKeyboard。

三、 封装

public void sendkeys(WebElement el, String str) {
    try {
        el.click();
        // 如弹出的是数字键盘,目前WDA无法识别,则使用点击数字按钮完成
        if (driver.findElementByXPath("XCUIElementTypeKeyboard") == null) {
            String xpath = "/XCUIElementTypeApplication/XCUIElementTypeWindow[4]/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther[2]";
            char[] keys = str.toCharArray();
            for (int i = 0; i < keys.length; i++) {
                String x = String.valueOf(keys[i]);
                if (!x.equals("0")) {
                    driver.findElementByXPath(xpath + "/XCUIElementTypeButton[" + x + "]").click();
                } else {
                    // 数字0为第11个Button
                    driver.findElementByXPath(xpath + "/XCUIElementTypeButton[11]").click();
                }
            }
            // 完成按钮为第10个Button
            driver.findElementByXPath(xpath + "/XCUIElementTypeButton[10]").click();
        } else {
            el.sendKeys(str);
        }
    } catch (Exception e) {
        TraceUtil.logTrace(e);
    }
}

四、 调用执行

@Test
public void test_case() throws Exception {
    driver.findElementByName("注册").click();
    WebElement phone = driver.findElementByXPath(
            "/XCUIElementTypeApplication/XCUIElementTypeWindow[1]/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther[2]/XCUIElementTypeTextField[1]");
    sendkeys(phone, "13312345678");
    driver.findElementByName("发送验证码").click();
    WebElement code = driver.findElementByXPath(
            "/XCUIElementTypeApplication/XCUIElementTypeWindow[1]/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther[2]/XCUIElementTypeTextField[2]");
    sendkeys(code, "123456");
}
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 15 条回复 时间 点赞

ATX 底层用的也是 WDA,实际使用是可以 send_keys 的。不能说是 WDA 的问题,只能说是 appium 没有提供支持

codeskyblue 回复

我试过 Appium 和 Macaca 都是这样的情况。下来试用一下 ATX

adfghzhang 回复

你可以单独用下 https://github.com/openatx/facebook-wda 这个是 ATX 的子模块,依赖少

如果这样执行的话,速度会不会是肉眼速度的输入?

刚在 10.2 模拟器上试了可以 send_keys 呀,1.6.3 版本。

lbw 回复

场景是数字键盘,全键盘是可以输入的

codeskyblue 回复

实验了,结果还是不能输入,数字键盘能够正常弹出,报错信息如下:

Traceback (most recent call last):
  File "D:\Program Files\eclipse\plugins\org.python.pydev_5.5.0.201701191708\pysrc\pydevd.py", line 1537, in <module>
    globals = debugger.run(setup['file'], None, None, is_module)
  File "D:\Program Files\eclipse\plugins\org.python.pydev_5.5.0.201701191708\pysrc\pydevd.py", line 976, in run
    pydev_imports.execfile(file, globals, locals)  # execute the script
  File "E:\workspace\testATX\atx\__init__.py", line 23, in <module>
    s(className="XCUIElementTypeTextField").set_text("18612345678")
  File "D:\Python27\lib\site-packages\wda\__init__.py", line 586, in set_text
    return self._property('value', data=json.dumps({'value': list(text)}), method='POST')
  File "D:\Python27\lib\site-packages\wda\__init__.py", line 574, in _property
    return self._request(data, suburl='element/%s/%s' % (eid, name), method=method).value
  File "D:\Python27\lib\site-packages\wda\__init__.py", line 392, in _request
    return httpdo(urljoin(self._base_url, suburl), method, data=data)
  File "D:\Python27\lib\site-packages\wda\__init__.py", line 74, in httpdo
    raise WDAError(r.status, r.value)
wda.WDAError: WDAError(status=13, value=Error Domain=com.facebook.WebDriverAgent Code=1 "Keyboard is not present" UserInfo={NSLocalizedDescription=Keyboard is not present})

adfghzhang 回复

看来只能用你那种办法了

codeskyblue 回复

appium 那边的人叫我提 issue 给 wda😂

adfghzhang 回复

提了估计他们也解决不了

adfghzhang 回复

可能用的语言不一样,python 写的 send_keys 正常。

lbw 回复

你这是什么 app,用 inspector 看一下键盘区域有不有 XCUIElementTypeKeyboard 控件。

adfghzhang 回复

我们公司自己的 app。

lbw 回复

嗯,你这个键盘是有 XCUIElementTypeKeyboard,WDA 底层是支持的,所以能够识别。但是我这弹出的键盘不是这样的。所以有点坑

adfghzhang 回复

请问你的问题解决了吗,我这也遇到 Keyboard is not present\" UserInfo={NSLocalizedDescription=Keyboard is not present。你怎么处理的

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