xcode7 UI 测试

来源:互联网 发布:儿童绘画软件哪个好 编辑:程序博客网 时间:2024/05/18 18:54

xcode7 UI 测试

原文地址:https://medium.com/@larcus94/ui-testing-with-xcode-7-221d16bad276
译者:孟祥月 博客:http://blog.csdn.net/mengxiangyue

大约两个两个星期之前,Apple发布了Xcode 7 的第一个beta版本,同时也带来了一些小巧的新特性,比如UI 测试。除了Swift,这个是最让我兴奋的一个特性。我迫不及待的想要去试试它。UI 测试并不是什么新的东西;KIF在2011年开始就已经做这方面的事情了。它是一个很强大的工具,但是它也有它得局限性:它运行缓慢、并不是100%可靠,并且它依赖于私有API。所以一个官方的解决方案听起来还是感觉很好的。

这个解决方案被集成在了Apple的单元测试框架XCTest中。使用它跟使用KIF很像。但是它使构建在一个新版本的UIAutomation之上,它是稳定的可信赖的。由于它被构集成进了Xcode,一些强大的特性,比如UI 记录(UI recording)和自动截屏,使它十分有用并且十分易用。

在接下来的章节中,我将讨论这两个框架最大的不同。

灵活性(Flexibility)

接下来,我开始为ImagePickerSheetController重写UI测试。ImagePickerSheetController是我的一个开源项目。它是一个自定义的在iMessage中我们选择一张图片的时候弹出来的action sheet(译者注:这个框架的功能可能描述不准确,因为在github上下载下来代码,我这里运行出错)。

MacDown Screenshot

我想重写的第一个测试是非常基本的。我只是想测试一下,当我点击cancel按钮的时候,这个controller能不能消失。

func testDismissal() {    let imageController = ImagePickerSheetController()    imageController.addAction(ImageAction(title: “Cancel”))    rootViewController.presentViewController(imageController, animated: true, completion: nil)    tester().tapViewWithAccessibilityLabel(“Cancel”)    tester().waitForAbsenceOfViewWithAccessibilityIdentifier(ID)}

这个看起来十分简单,但是它不可能使用XCTest去实现。问题是Xcode UI测试不允许你访问真实的app。这个API紧紧是扮演了一个代理的角色。尝试直接获取一个view代理现在使用的XCUIElement,它只能表示这个view,并不能工作。

在WWDC的Developer Tools Labs,我被告知:XCTest的一个主要的目标就是使app更加的可测试化。我认为这个是有意义的,并且我开始重写我的一个叫做Crimson的app的测试。

在一系列基本的测试后,我开始测试‘accent view’(译者注:上图中的e和不同音调的View)。它能够显示一个字母的不同音调。我想要测试下面的两个方面:

  • 当它出现得时候,第一个字母应该被选中,这里是‘e’
  • accent view应该有一个颜色的key(原文:the accent view should have the same color as the key)

首先,我认为不可能为这些去写测试。在以前,你不能研究一个真正得view并且去检查它的属性(原文:As before, you can’t just investigate the actual view to check the properties.)。在一次查看文档的过程中,我偶然的返现了一个XCUIElement的一个叫做value的十分有用的属性。

/*! The raw value attribute of the element. Depending on the element, the actual type can vary. */var value: AnyObject? { get }

它的作用就是返回UI element的accessibilityValue。这使在测试中获取属性成为了可能。所以现在的事情就是我需要在accent view上设置accessibilityValue。

class AccentView: UIView {    var selectedLetter: String {        didSet {            accessibilityValue = selectedLetter        }    }}

直到我先要获取color之前,这个都工作得很好。由于accessibilityValue的类型是String,而不是Dictionary,它不可能获取到二级属性。另一反面,与accessibilityIdentifier相比,accessibilityValue是用户界面上的。设置accessibilityValue为一些难以理解的值,比如颜色,是非常不好的实践,并且完全违背了其目的。

写第二个测试也是不可能的。然而检查一个element的frame或者label是非常简单的,它几乎也不可能测试其他的东西。

性能(Performance)

为了测试两个框架的性能,我写了一个例子工程,包含3个测试。为了模拟合理的测试流程,每一个测试执行了20次,总共60次。

对于第一项测试,我按照文档实现了这个测试。对于XCTest,需要在每次测试的时候重启app。KIF不需要重启,这个使它在第一项测试上由于XCTest。

第二个测试,使用导航返回的方式重置app的状态代替了重启。

对于第三个测试,取消了所有的动画。

像我们在第一次基准测试中看到的一样,每次重启app使一组测试非常慢。令人意外的是,UI测试模板中建议使用重启的这种方式,而不是通过导航,因为这种方式在大多数情况下是不必要的。

第二次测试表明在一般得情况下,XCTest比KIF稍微快一点。当然也得注意,虽然这里只是节省了10秒,但是在一个比较大的并且一天需要执行好多次的一组测试中,还是能够节省不少的。

最后一个测试显示XCTest是十分亮眼的。然而取消动画对于每个项目来说只是一个可选项。想象一下,项目中有许多自定义的动画,测试需要验证这些动画是否按照我们预期的执行。

工作区使用不同得启动环境去控制app的配置,将这些测试分配到不同得类中。

class UITests: XCTestCase {    private var launched = false    let app = XCUIApplication()    override func setUp() {        super.setUp()        continueAfterFailure = false        launchIfNecessary()    }    private func launchIfNecessary() {        if !launched {            launched = true            app.launchEnvironment = [“animations”: “0”]            app.launch()        }    }    func testDetail() { ... }    func testPopover() { ... }    func testActionSheet() { ... }}

AppDelegate设置启动环境的配置。

class AppDelegate: UIResponder, UIApplicationDelegate {    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {        if NSProcessInfo.processInfo().environment[“animations”] == “0” {            UIView.setAnimationsEnabled(false)        }        ...        return true    }}

这个能够减少你等待测试完成的时间。

结论(Conclusion)

XCTest使简单得UI测试更加容易。但是比较高级的测试将会很难或者不可能。KIF更加零落。

然后跟KIF比较,XCTest在找到UI elements上更加轻巧、快速。另外取消动画,XCTest运行相当快。

尽管我希望将UI Test集成到项目中,但是我还是放弃在我的项目中重写他们。我不能找到一个重写所有测试的方法。

  • Labs at WWDC
  • Source Code
  • UI Testing in Xcode WWDC video
  • KIF GitHub repository
1 0
原创粉丝点击