前提:测试的App基于iOS 9.3 以及之后的系统版本,Xcode软件版本不低于7,才可以使用该技术,UI Testing 在易用性上比 KIF 这样的框架要有所进步,随着 UI Testing 的推出,Apple 也将原来的 UI Automation 一系列内容标记为弃用。这意味着 UI Testing 至少在今后一段时间内将会是 iOS 开发中的首选工具。但是我们也应该看到,基于 Accessibility 的测试方式有时候并不是很直接。在这个限制下,我们只能得到 UI 的代理对象,而不是 UI 元素本身,这让我们无法得到关于 UI 元素更多的信息 (比如直接获取 UI 元素中的内容,或者与 ViewController 中的相关的值),现在的 UI Testing 在很大程度上还停留在比较简易的阶段,适合保证App的主流程的顺畅运行、用于回归测试。在技术探索过程中,发现测试脚本在iOS 11系统表现很好,但是在iOS 9等系统上会出现找不到按钮的情况等问题。随着iOS系统版本的推进,相信XCUITest技术的兼容性、性能会不断得到改进。
PS: 首先请允许我宣传一波,iOS的UI自动化测试,我还没见过速度更快更稳定的UI自动化技术,这毕竟是Apple官方主导的,每年都会提升的测试技术。一个算不上缺点的缺点:需要了解些Swift等iOS编程知识,但是现在的Swift、Python、Kotlin等现代化的语言都很容易入门了,不用担心,况且实现UI自动化的脚本不会涉及太多语言上过深的知识。
一、给已有的Xcode源码工程添加UITest功能:
1.在项目中新建UITest模块
(1)如果是新建空白项目,可以勾选Include UITest相关选项。
(2)如果是已有项目(比如pull下来的完整的iOS客户端代码),在Xcode中点击File->New->Target
如图选择:
一、给已有的Xcode源码工程添加UITest功能:
1.在项目中新建UITest模块
(1)如果是新建空白项目,可以勾选Include UITest相关选项。
(2)如果是已有项目(比如pull下来的完整的iOS客户端代码),在Xcode中点击File->New->Target
如图选择:
点击Next,进入选项配置:
第一步:选择Project。
第二步:选择最底部的Target to be Tested,这里选择Dev结尾的包,因为该包在模拟器上测试不需要签名。
此时Product Name会根据选项自动生成。切换自己需要的语言(Objective-C、Swift(推荐))
完成。
此时,项目中增加了新的以[Target+UITest]命名的文件夹,如图:
当前选中的与文件夹同名的(UITests结尾)文件就是我们可以编写测试代码的文件了。
点击Next,进入选项配置:
第一步:选择Project。
第二步:选择最底部的Target to be Tested,这里选择Dev结尾的包,因为该包在模拟器上测试不需要签名。
此时Product Name会根据选项自动生成。切换自己需要的语言(Objective-C、Swift(推荐))
完成。
此时,项目中增加了新的以[Target+UITest]命名的文件夹,如图:
当前选中的与文件夹同名的(UITests结尾)文件就是我们可以编写测试代码的文件了。
二、常用基本操作
1.点击某个按钮,比如登录按钮
app.buttons["登录"].tap()
2.普通输入框输入文本
app.textFields["手机号"].tap() //要先聚焦文本框,才能继续输入
app.textFields["手机号"].typeText("13038865629")
注意密码输入框等输入文本会变成小圆点的地方使用app.secureTextFields["密码"]。
3.下拉刷新
app.swipeDown()
4.滚动查看屏幕下方的内容,上拉加载更多
app.swipeUp()
也可以左右滑动切换页面:app.swipeLeft/Right()
5.切换tab
app.tabBars.buttons["首页"].tap()
app.tabBars.buttons["行情"].tap()
6.让应用程序等待一会(比如数据载入的时候,或者延时操作)
sleep(3) //单位是秒
7.判断元素是否存在
if app.buttons["确定"].exists {
//点击确定按钮
}
8.使用断言来验证App界面的状态
XCTAssert(app.buttons["个人中心"].count == 1)
//count属性表示符合查询条件的结果个数
9.从导航栏返回上级页面
app.navigationBars["消息中心"].buttons["返回"].tap()
10.使用正则匹配,操作列表元素(进阶)
let addButton = app.tables.cells.matching(NSPredicate(format: "label CONTAINS %@", "铜")).element(boundBy: 0)
addButton.tap()
//NSPredicate(format: "label CONTAINS %@", "铜") -- 筛选包含‘铜’字的文本
//element(boundBy: 0) -- 查询结果的第一个元素,该页面结果显然是唯一的,这种情况下可以使用firstMatch属性来代替,提升效率。
三、通过命令行执行UI自动化测试
做平台集成需要了解的知识
首先进入项目中包含PreciousMetals.xcproject文件的文件夹下,然后执行:
xcodebuild test -workspace PreciousMetals.xcworkspace -scheme PreciousMetalsDevUITests -destination 'platform=iOS Simulator,name=iPhone X,OS=12.0'
-workspace参数: 项目的工程文件,和使用xcode打开客户端项目时双击的文件是同一个。
-scheme参数:使用的配置或者方案,就是测试哪个目标,测试过程有什么代码覆盖等要求都可以在scheme中配置。
-destination参数可以指定多个,从而实现一个命令执行多个模拟器的兼容测试。
四、测试报告的优化
1.优化测试报告的可读性(层级关系),同时改进了源码可读性。
XCTContext.runActivity(named: "测试直播间内 - 子Tab切换", block: { _ in
app.otherElements["策略"].tap()
app.otherElements["提问"].tap()
app.otherElements["介绍"].tap()
app.otherElements["节目"].tap()
app.otherElements["直播"].tap()
})
效果图:控制台输入,即为
可以看到Activity是有层级的。
每个动作还会有完成该动作的具体过程,比如下图中的绿色部分,就是输入浏览器URL这个动作的具体过程:
2.增加指定元素的截图到结果集:
XCTContext.runActivity(named:"收集一波关键截图") { activity in
//捕捉第一个cell的截图
//也可以使用XCUIScreen.main.screenshot()来捕捉一张全屏幕截图
let cell = app.cells.element(boundBy:0)
let cellAttachment = XCTAttachment(screenshot: cell.screenshot())
cellAttachment.lifetime = .keepAlways
activity.add(cellAttachment)
}
这是很好用很高效的官方测试技术,希望愿意认识swift等iOS语言的测试人员来交流使用。
下一篇:
https://www.jianshu.com/p/e6df6c6024ac
番外篇: