iOS 测试 ios+appium 自动化中遇到的问题 (求助问题 2

醋精测试媛 · 2021年06月03日 · 最后由 Rise 回复于 2022年02月07日 · 4501 次阅读

1.如何隐藏数字键盘

搜了一下隐藏键盘的操作,发现可以通过 driver.hidekeyboard(key_name=Done) 等来解决,但是,如果是数字键盘该如何隐藏呢?

例如这样的键盘:

即使是( https://testerhome.com/topics/18388 )这种,里面还是有 Done 的,但是不知道为什么,测试的这个 iPhone 没有,只能通过点击旁边的关闭键盘,但是我使用 driver.hidekeyboard() 即里面不加参数,则会出现以下错误:

>       raise exception_class(message, screen, stacktrace)
E       selenium.common.exceptions.InvalidElementStateException: Message: Error Domain=com.facebook.WebDriverAgent Code=1 "Did not know how to dismiss the keyboard. Try to dismiss it in the way supported by your application under test." UserInfo={NSLocalizedDescription=Did not know how to dismiss the keyboard. Try to dismiss it in the way supported by your application under test.}

不加参数应该只能兼容安卓,请问这种情况下这种键盘应该如何隐藏呢?

2.ios 无法获取输入框中的值:

问题描述问题描述问题描述


这种类型的输入框,我用 appium inspector 打开,只有这些属性:

确实属性比较少,问了开发,说输入框中的值存在于 text 中,然而输出后为空。

属性 value 也输出了是空。

请问大家遇到过这种情况吗?我第一次接触 ios,所以遇到了很多坑,搜了之后,Stack Overflow 有一个人和我情况差不多( https://stackoverflow.com/questions/61668767/appium-ios-13-above-xcuielementtypetextfield-value-attribute-shows-obj-as),但是没有解答方法。

ps: ios 的输入框的 text 实际上是获取的什么呢?label?name?

共收到 31 条回复 时间 点赞

尝试了 element.send_keys("\n") 也没有用。

而且对输入框 clear() 无效,appium ios 坑这么多的吗 😭

笨方法,点击一个不会有响应事件的位置关闭键盘

木月 回复

请问 clear 无效的情况遇到过吗

开发和我都不知道怎么弄

1 的问题比较容易解决。你先把 “完整的键盘” 截图出来,你给的截图应该是不完整的,缺少了上边一排元素

Thirty-Thirty 回复

这就是完整的键盘,上面没有一行,我知道,有的上面有一个 Done,但是我的没有

那你需要对照下产品设计说明书,看这个键盘的实现是否符合设计要求。说明书没描述清楚就直接问产品经理,这个键盘实现是不是符合 ta 的期望。

点击一下键盘外面的某个元素(除输入框)是不是就自动隐藏了?

Thirty-Thirty 回复

这不是 ios 的自带键盘吗

关于第二条的补充:
用腾讯 qq 进行测试,也是和我用公司软件测试一样,测试脚本:

sleep(10)
print("1", driver.find_element_by_ios_predicate('name == "帐号"').text)
driver.find_element_by_ios_predicate('name == "帐号"').clear()
print("2", driver.find_element_by_ios_predicate('name == "帐号"').text)
driver.find_element_by_ios_predicate('name == "帐号"').send_keys("123456")
print("3", driver.find_element_by_ios_predicate('name == "帐号"').text)

输出结果:

1 QQ号/手机号/邮箱  # 说明这里text取得是value
2 QQ号/手机号/邮箱  # 我看了app,这里clear无效了
3    # 这个地方,是在默认的qq号后面连着添加的

APP Inpector:

开始怀疑自己是不是真的哪里做的不对?还是这是常见现象

大意了,没审好题:)

2 的问题,我们之前遇到过的类似情况是,表面上看是个输入框,其实上层还有别的不止一个元素,其中的一个元素才是供输入用的,也就是你们开发所说的那个 text,我们操作这个元素是可以输入的,你是不是没找对啊?
不知道会不会又双叒叕审错题,呵呵!

Thirty-Thirty 回复

可以看一下这个 page_source :

<?xml version="1.0" encoding="UTF-8"?><AppiumAUT><XCUIElementTypeApplication type="XCUIElementTypeApplication" name="QQ" label="QQ" enabled="true" visible="true" accessible="false" x="0" y="0" width="375" height="667" index="0">
  <XCUIElementTypeWindow type="XCUIElementTypeWindow" enabled="true" visible="true" accessible="false" x="0" y="0" width="375" height="667" index="0">
    <XCUIElementTypeOther type="XCUIElementTypeOther" enabled="true" visible="true" accessible="false" x="0" y="0" width="375" height="667" index="0">
      <XCUIElementTypeOther type="XCUIElementTypeOther" enabled="true" visible="true" accessible="false" x="0" y="0" width="375" height="667" index="0">
        <XCUIElementTypeOther type="XCUIElementTypeOther" enabled="true" visible="true" accessible="false" x="0" y="0" width="375" height="667" index="0">
          <XCUIElementTypeOther type="XCUIElementTypeOther" enabled="true" visible="true" accessible="false" x="0" y="0" width="375" height="667" index="0">
            <XCUIElementTypeOther type="XCUIElementTypeOther" enabled="true" visible="true" accessible="false" x="0" y="0" width="375" height="667" index="0">
              <XCUIElementTypeOther type="XCUIElementTypeOther" enabled="true" visible="false" accessible="false" x="0" y="0" width="375" height="667" index="0"/>
              <XCUIElementTypeImage type="XCUIElementTypeImage" name="登录界面" label="登录界面" enabled="true" visible="false" accessible="true" x="0" y="0" width="375" height="667" index="1"/>
              <XCUIElementTypeImage type="XCUIElementTypeImage" enabled="true" visible="true" accessible="false" x="0" y="0" width="375" height="667" index="2"/>
              <XCUIElementTypeImage type="XCUIElementTypeImage" enabled="true" visible="false" accessible="false" x="133" y="108" width="109" height="51" index="3"/>
              <XCUIElementTypeOther type="XCUIElementTypeOther" name="帐号框" enabled="true" visible="true" accessible="false" x="40" y="190" width="295" height="56" index="4">
                <XCUIElementTypeOther type="XCUIElementTypeOther" enabled="true" visible="true" accessible="false" x="40" y="190" width="295" height="56" index="0"/>
                **<XCUIElementTypeTextField type="XCUIElementTypeTextField" value="QQ号/手机号/邮箱" name="帐号" label="" enabled="true" visible="true" accessible="true" x="102" y="190" width="170" height="56" index="1"/>**
                <XCUIElementTypeButton type="XCUIElementTypeButton" name="帐号列表" label="帐号列表" enabled="true" visible="true" accessible="true" x="292" y="190" width="25" height="56" index="2"/>
                <XCUIElementTypeButton type="XCUIElementTypeButton" name="头像" label="头像" enabled="false" visible="false" accessible="false" x="50" y="198" width="40" height="40" index="3">
                  <XCUIElementTypeImage type="XCUIElementTypeImage" enabled="true" visible="false" accessible="false" x="50" y="198" width="40" height="40" index="0"/>
                </XCUIElementTypeButton>
              </XCUIElementTypeOther>
              <XCUIElementTypeOther type="XCUIElementTypeOther" enabled="true" visible="true" accessible="false" x="40" y="258" width="295" height="56" index="5">
                <XCUIElementTypeSecureTextField type="XCUIElementTypeSecureTextField" value="输入密码" name="密码" label="" enabled="true" visible="true" accessible="true" x="90" y="258" width="195" height="56" index="0"/>
              </XCUIElementTypeOther>
              <XCUIElementTypeButton type="XCUIElementTypeButton" name="登录按钮" label="登录" enabled="true" visible="true" accessible="true" x="152" y="371" width="71" height="71" index="6"/>
              <XCUIElementTypeButton type="XCUIElementTypeButton" name="手机号登录" label="手机号登录" enabled="true" visible="true" accessible="true" x="47" y="585" width="62" height="26" index="7"/>
              <XCUIElementTypeButton type="XCUIElementTypeButton" enabled="true" visible="true" accessible="false" x="135" y="593" width="2" height="10" index="8"/>
              <XCUIElementTypeButton type="XCUIElementTypeButton" name="找回密码" label="找回密码" enabled="true" visible="true" accessible="true" x="162" y="585" width="51" height="26" index="9"/>
              <XCUIElementTypeButton type="XCUIElementTypeButton" enabled="true" visible="true" accessible="false" x="239" y="593" width="2" height="10" index="10"/>
              <XCUIElementTypeButton type="XCUIElementTypeButton" name="新用户注册" label="新用户注册" enabled="true" visible="true" accessible="true" x="266" y="585" width="62" height="26" index="11"/>
            </XCUIElementTypeOther>
          </XCUIElementTypeOther>
        </XCUIElementTypeOther>
      </XCUIElementTypeOther>
    </XCUIElementTypeOther>
  </XCUIElementTypeWindow>
  <XCUIElementTypeWindow type="XCUIElementTypeWindow" enabled="true" visible="false" accessible="false" x="0" y="0" width="375" height="667" index="1">
    <XCUIElementTypeOther type="XCUIElementTypeOther" enabled="true" visible="false" accessible="false" x="0" y="0" width="375" height="667" index="0"/>
  </XCUIElementTypeWindow>
  <XCUIElementTypeWindow type="XCUIElementTypeWindow" enabled="true" visible="false" accessible="false" x="0" y="0" width="375" height="667" index="2">
    <XCUIElementTypeStatusBar type="XCUIElementTypeStatusBar" enabled="true" visible="false" accessible="false" x="0" y="0" width="375" height="20" index="0"/>
  </XCUIElementTypeWindow>
</XCUIElementTypeApplication></AppiumAUT>

加粗部分是我取的元素,我想我应该没有取错?

print("2", driver.find_element_by_ios_predicate('name == "帐号"').text)

是的,你找的元素是对的,调用 clear 不起效这边也遇见过,通过全选后删除解决了

Thirty-Thirty 回复

请问为何我去获取这个输入框的 text,会出现 11 楼我说的那种情况?

如果你试了有效,既然已经找到 workaround,又何必苦苦寻找完美的 solution 呢,凡事不可太认真啊!

Thirty-Thirty 回复

不是,输入新的值,即用 send_keys(),它是在已有的内容后面添加(这确实是 clear 的问题,我也确实可以用其他方法解决)。

但是,我的意思是,我发现无法获取用户在输入框输入的值,并且对 qq 等 app 进行了验证,也问了公司 app 的开发,说输入框中的值存在于 text 中,然而公司的 app 打印出来为空,而 qq 的情况如上面所示(取得是 value 属性的值)。而且输入新的值后,再获取 text,是空的。

我是问的这个情况。

懂你的意思了。
我认为你们的 APP 在接收到 sendkeys(“123”) 后并没有立即把 123 赋值给 text,这时候取到的值就是 send 之前的值即为空。进一步猜想,你通过脚本把这个登录页面需要的数据都输入并点击登录,应该是可以登录进去的,也就是说,这个赋值动作可能发生在登录按钮被点击的时候 (你可以跟开发确认,或直接问他这个赋值发生时间)。
@chenhengjie123 你怎么看?

Thirty-Thirty 回复

刚爬完楼。分享下我的观点:

问题一:试下点击应用内其他非输入框的空白处,是否可以隐藏?
问题二:不确定你们开发有没有用自己额外自定义的 UI 组件(这个从 pagesource 看不出的,因为控件树拿到的类名,都是 iOS 系统提供的少数几个基础类,有可能和开发写代码时看到的组件封装好的名字完全不一样。属性名同理)。

XCUITest 获取到的元素属性,应该只有基类固定的几个,如果用了其他的属性来存,有可能 XCUITest 获取不到。建议你问下你们开发,或者直接找开发拿项目源码来看看吧,看下怎么存的,放到了啥属性值里。 xcode 本身也有自带查看整个界面层次结构的工具(可以看看 https://blog.csdn.net/PZ0605/article/details/50670285 ),这个工具相对会更可靠。

PS: @ 醋精测试媛 看到你做 UI 自动化已经有一段时间了,也发过不少求助帖,确实也是一些网上不容易直接搜到的疑难杂症。个人经验,这类问题之所以不常见,和你测试的应用具体怎么实现是强相关的。所以网上其他同学能给到的大多只能是参照思路,真正去探究到核心原因以及怎么解决最合适,还是需要你去熟悉被测应用的源代码,辅以熟悉 OC/Swift、XCUITest 框架以及 iOS SDK 提供的各个基本的 UI 控件,能搞清楚每个基本控件的属性和 XCUITest 乃至 appium 拿到的属性的对应关系。

提个小建议,可以到网上找门 iOS 开发入门课学一下(我当时看得是网易公开课里斯坦福的 iOS 开发课,但估计有点老了,你可以找下新的)。不要求学到能自己独立写 app,但仿照课程内容写一遍后,能让你对 iOS 开发的套路有大概的了解,也便于你后面看源码、和开发准确交流。

暂时没遇到过

关于问题 2,推荐 xpath 定位

  • 键盘的问题:目前我遇到的数字都是拿不到的,特殊键 shift, delete, more, space 等可以通过 ACCESSIBILITY_ID 拿到,大小写敏感。隐藏基本只能靠点击键盘以外的区域隐藏,或再点击一次输入框
  • 元素的问题:
    • 可以尝试使用 set_value()
    • 拿 value 值可以用 get_attribute
    • clear/send_keys 之后元素定位发生变动,原来的定位无法拿到真正的元素:
      • 元素定位不一样,需要使用变化后的定位元素
      • 元素定位没有变,属性发生变化,如 visible,appium 显示的 visible 有时候是不正确的
      • 元素定位没有变,属性未发生变化,但是多了一个 visible 为 false 的相同元素,该元素才能拿到 text
    • 可以尝试使用其他定位方式如 class_chain 或 xpath(封装的问题导致)。多数情况下使用 xpath 可以解决问题(很多时候是 visible 属性问题),少数情况下 xpath 拿不到,反而需要用 class_chain 和 predicate
Thirty-Thirty 回复

谢谢,我去确认一下这个方面的可能性。

陈恒捷 回复

谢谢你的建议,之前遇到这个问题,我就有这方面的意向,但是没有找到比较合适的教程,尝试下载了一个很常见的用于自动化测试的 iOS 的 demo 源代码,但是当时看了还是一头雾水,确实是需要再找找资料把这方面的基础补充一下。

上拉不能隐藏键盘么?

笑哼 回复

不行

我分享下我当时的学习路线,你可以参考下:

1、看苹果开发者网站的 object-c 教程,理解 oc 的基本套路(比如 .h/.m 的区别,函数及类的定义,内置数据类型等)
2、看苹果开发者网站一些指引教程,比如经典的 todo list app,会从 mvc 分层设计开始,先定义每一层的 .h ,然后再实现各层的功能,手把手级别的教程实现人生中第一个 ios app 。(刚找了下,苹果官网已经没有这个例子了,新的例子是 https://developer.apple.com/tutorials/swiftui
3、看一下网易公开课里 ios 开发课程,我当时看得斯坦福的课,不过讲得比较深,所以是当时春节前相对事情没那么多的时候集中学习的,没全部看完,大概看了前 5 节左右。现在慕课什么的课程应该也挺多的,可以找个合适自己的看,边看边自己按照里面写得去实现代码。一般这种教程没有第二步那么手把手,刚好锻炼下自己怎么通过思路描述去完成代码编写。
4、完成第二步后,其实也可以开始在项目中看开发代码了,主要看本地迭代开发修改的内容,因为自己知道实现的功能有哪些,感受会更明显。开发代码建议越早看越好,因为很多入门课程都在教你怎么用 storyboard ,但实际项目为了方便复用,很多都是直接用代码手撸界面的,会有种教程都在 level 1 ,实际项目直接跳到 level 5 这种感觉,所以早点看代码可以避免自己陷入自己已经完全懂开发这种错觉。

基本上每天抽 30 分钟-1 小时做这些,第一步大概花了 1 周,第二步 2 个周末(需要完整时间,避免思路被打断),第三步春节前大概 3-4 天(也是比较完整的时间)。

https://testerhome.com/topics/30318
这个问题,楼主是怎么解决的,可以讲讲吗,目前也遇到了这个问题

mt 回复

可以看看我艾特的两个人的答案。我添加了 exit 0

楼主还在吗,也碰到了这个问题,没有 done,最后是怎么处理的?

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