iOS 测试 XCUITest-在 iOS 测试中的妙用 (番外篇)

李鹏 · 2019年06月03日 · 最后由 李鹏 回复于 2020年12月17日 · 6024 次阅读
前言吹一波

  iPhone 的自动化测试,只要有 Mac 条件,XCUITest 就是绝配啦
  (😎Apple 爸爸的先天优势好吧😎)

XCUITest 的基本知识参见:

https://www.jianshu.com/p/adb289c1d839

关键词:iOS UI 自动化 Xcode 测试 Swift Mac

1.脱离 iOS App 源码进行 UI 自动化

  「该部分手把手教学,再不行可能是基础知识匮乏,辛苦 google 吧」

  可能能做出很多夸张的事情,看你发挥啦!

  鉴于之前的一些 Demo 都是基于 App 源码本身添加 target 来展开 UI 自动化测试的,后来实验发现完全不用依赖源码。

  但是结合源码的 UITest 可以方便增加 accessbility 属性来配合元素定位,也可以发现一些非主线程更新 UI 等危险操作的存在(还是有不少好处的)。

创建一个新的 Xcode 项目:

Xcode->File->New->Project(快捷按键 Shift+Command+N )

  项目模板如果不太懂就选择 Single View App 吧。该项目作为 UITest 这个 target 的依赖,没有什么实质作用。

下一步注意包含 Include UI Tests,项目名称和组织名称你开心就好。

完成后如图所示:

代码-Safari 浏览器,载入百度网页的过程

let safariApp = XCUIApplication.init(bundleIdentifier: "com.apple.mobilesafari") 
let wechatApp = XCUIApplication(bundleIdentifier: "com.tencent.xin") 
let qqApp = XCUIApplication(bundleIdentifier: "com.tencent.mqq")
 //如果要测试自己公司的App,那么问下开发bundle identifier就好了,上面的三个分别是 iPhone 自带的浏览器、腾讯微信、腾讯 QQ 程序 
safariApp.launch() 
app.buttons["URL"].tap() 
//防止如果浏览器打开后有一个默认的网页,则点击输入框右边👉的叉号来清空 
if (app.buttons["清除文本"].exists){ 
    app.textFields["URL"].buttons["清除文本"].tap()
 } 
app.textFields["URL"].typeText("http://www.baidu.com") 
//点击键盘上的确认按钮,也是前往按钮 app.buttons["前往"].tap() 
//至此,完成了打浏览器,载入百度网页的过程

  这不是官方推荐的操作,因为此时 app 对象不是默认的宿主 app。也就是wait for app to idle等操作无法正确地合理地判断 app 状态了。
还是推荐在被测试的源码内集成 XCUITest Target。

2.「多 App 交互」测试外部 App 登录(微信登录、微博登录、QQ 登录)

  交给 XCUITest 自动化,都是极速完成

  建议打开 XCUITest 的脚本录制功能操作一遍来构成基本代码。

  速度比手工都快速,各种 app 的交互成为可能,足见 XCUITest 的巨大潜力。

  实例是网页调起 QQ 等软件进行登录的过程,同样,自己的 App 调起这些常用的 App 进行登录类似。

  注意操作 QQ、微信等其它 app 的时候使用上文代码中定义的 qqApp、wechatApp 等对象。

  也就是说操作的不同的 App 都要是对应的 XCUIApplication 对象。

3.「important」查看 XCUIElement 的结构树(当前的 UI 元素树)

在断点处,lldb 命令行执行:

po app.debugDescription()

  如果查看不方便,将选中的部分复制到 SublimeText 等第三方文本编辑器

将 \n 替换成换行 Enter 键,效果如下:

是 Safari 浏览器打开一个登陆网页之后的元素树的一部分。

4.万能点击

(不建议,但是极端情况可以解决问题)

  如果遇到实在处理不了的情况,比如 XCUITest 元素树中都找不到某元素

  可以考虑使用点击操作暂时绕过

【充电站】了解 UI 在 iOS 系统中的倍数渲染,2x、3x 等

比如 Xs Max 这样的高分辨率肯定是 3x 渲染了。

icon_alipay.png → iPhone 早期的低分辨率手机 (不考虑)

icon_alipay@2x.png → iPhone4/4S/5/5S/6/6S/7 对应尺寸,这就是 2 倍图

icon_alipay@3x.png → iPhone6P/6SP/7P 使用的尺寸,3 倍图,也就是现在高端 iPhone 使用的图

  举栗子:如果 iPhone Xs Max (UI 图 = 3x 机型) 截图在 Photoshop 中测量出的要点击的点的位置是 [x=30,y=18],则代码中 tapAtPoint(x,y)的取值应该是 [x=10,y=6]

下面这个函数 Demo 可以直接粘贴,然后调用,点击 App 内的某个坐标的点。

func tapCoordinate(in app:XCUIApplication, at xCoordinate: Double, and yCoordinate: Double) { 
    let normalized = app.coordinate(withNormalizedOffset: CGVector(dx: 0, dy: 0)) 
    let coordinate = normalized.withOffset(CGVector(dx: xCoordinate, dy: yCoordinate)) coordinate.tap()
 }

比如这个图片:(实际像素尺寸为 1240*212 )

  QQ 和 微信 icon 的中心点在截图中的水平距离是 290 像素,代码中认为 1 倍距离,即距离为 290/3

共收到 4 条回复 时间 点赞

与 PC 交互 以及 Web,框架可以适用吗?

HelloHalo 回复

不可以啦,这是移动端 UI 自动化,可以交互 iOS app 以及 iOS 的 web 页面

李鹏 回复

flutter 支持吗

小丸子 回复

貌似需要开启 iphone 设置中的 voice over 相关选项。你可以试下,应该支持

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