我最近在忙着回归到过去测试代码的老路子,使用KIF和XCTest框架,这样会使得iOS中的测试变得简单。当我开始捣鼓KIF的时候,我用Swift写的应用出了点小问题,不过最终还是很机智的搞定了。在我写Swift的时候我还发现了不少Swift独有的模式,这是个令我相当愉快的事,所以我们可以拿来分享分享。

这里我用的示例Demo是自己开发的Seinfeld Quotes应用,现在我只是简单的测试添加条目的功能,下图是用KIF进行的测试:

Swift的KIF设置

设置KIF的话只要照着KIF README就好了。成功设置之后,一定要确认你在最外层的Bridging Header头文件里导入了KIF包,如下:

为了触发Bridging Header头文件的生成,我通常会先在目标里用Objective C写一个测试文件,然后当Bridging Header生成之后我就会删除它。

于是你觉得可以开始使用KIF了是吧,不过我想告诉你一个悲哀的事情,调试器(tester)在KIF里面是用#define定义的,而#define在Swift里面是不可用的!

当我按照@bnickel在Github上的Swift KIF Issue里的建议添加了一段扩展之后,KIF就能在Swift下兼容了。这里的修改相当小,而且尽量保证了tester和system语法上的原汁原味:

//
//  KIF+SwiftExtension.swift
//  SeinfeldQuotes
//
//  Created by Natasha Murashev on 10/5/14.
//  Copyright (c) 2014 NatashaTheRobot. All rights reserved.
//
 
extension XCTestCase {
     
    var tester: KIFUITestActor { return tester() }
    var system: KIFSystemTestActor { return system() }
     
    private func tester(_ file : String = __FILE__, _ line : Int = __LINE__) -> KIFUITestActor {
        return KIFUITestActor(inFile: file, atLine: line, delegate: self)
    }
     
    private func system(_ file : String = __FILE__, _ line : Int = __LINE__) -> KIFSystemTestActor {
        return KIFSystemTestActor(inFile: file, atLine: line, delegate: self)
    }
}

Accessibility Labels

KIF使用了Accessibility Labels来抓取任意屏幕上的View组件,因为Accessibility Labels可以轻易改变(比如说按钮标题改变)。而我偏好于用常数来标记每一个测试用的Accessibility Labels。

在Swift中我还发现了可以很好的在private扩展中通过枚举将这些Accessibility Labels放到一起:

// AddQuoteTests.swift
 
class AddQuoteTests: KIFTestCase {
     
}
 
// MARK: Setup Accessibility Labels
 
private extension AddQuoteTests {
    enum ButtonLabel: String {
        case Add = "Add"
        case Save = "Save"
    }
     
    enum NavBarTitle: String {
        case CreateQuote = "Create Quote"
        case ListQuotes = "Seinfeld Quotes"
    }
     
    enum TextFieldLabel: String {
        case QuoteContent = "Quote Content"
        case SceneDescription = "Scene Description"
    }
     
    enum TextInput: String {
        case QuoteContent = "My Awesome Quote"
        case SceneDescription = "My Scene"
    }
     
}

测试

我比较喜欢让自己的代码清晰可读,所以我测试乍看上去相当简单:

//
//  AddQuoteTests.swift
//  SeinfeldQuotes
//
//  Created by Natasha Murashev on 10/5/14.
//  Copyright (c) 2014 NatashaTheRobot. All rights reserved.
//
 
class AddQuoteTests: KIFTestCase {
     
    func testAddQuote() {
        tapAddButton()
        fillInQuoteData()
        saveQuote()
        assertNewQuoteCreated()
    }
     
}

而其实我把更多的细节实现在了一个private的扩展里:

class AddQuoteTests: KIFTestCase {
     
    func testAddQuote() {
        tapAddButton()
        fillInQuoteData()
        saveQuote()
        assertNewQuoteCreated()
    }
     
}
 
// MARK: Test Details
 
private extension AddQuoteTests {
     
    func tapAddButton() {
        tester.tapViewWithAccessibilityLabel(ButtonLabel.Add.toRaw(), traits: UIAccessibilityTraitButton)
        tester.waitForViewWithAccessibilityLabel(NavBarTitle.CreateQuote.toRaw(), traits: UIAccessibilityTraitStaticText)
    }
     
    func fillInQuoteData() {
        tester.enterText(TextInput.QuoteContent.toRaw(), intoViewWithAccessibilityLabel: TextFieldLabel.QuoteContent.toRaw())
        tester.enterText(TextInput.SceneDescription.toRaw(), intoViewWithAccessibilityLabel: TextFieldLabel.SceneDescription.toRaw())
    }
     
    func saveQuote() {
        tester.tapViewWithAccessibilityLabel(ButtonLabel.Save.toRaw(), traits: UIAccessibilityTraitButton)
        tester.waitForViewWithAccessibilityLabel(NavBarTitle.ListQuotes.toRaw(), traits: UIAccessibilityTraitStaticText)
    }
     
    func assertNewQuoteCreated() {
        tester.waitForViewWithAccessibilityLabel(TextInput.QuoteContent.toRaw(), traits: UIAccessibilityTraitStaticText)
        tester.waitForViewWithAccessibilityLabel(TextInput.SceneDescription.toRaw(), traits: UIAccessibilityTraitStaticText)
    }
}

这样就可以在Swift里进行各种各样的KIF测试了。

Swift中KIF测试的特点-b的更多相关文章

  1. Swift: 比较Swift中闭包传值、OC中的Block传值

    一.介绍 开发者对匿名函数应该很清楚,其实它就是一个没有名字的函数或者方法,给人直观的感觉就是只能看到参数和返回值.在iOS开发中中,它又有自己的称呼,在OC中叫Block代码块,在Swift中叫闭包 ...

  2. swift中的结构体和枚举

    Swift 里的结构体非常特殊. 类是面向对象编程语言中传统的结构单元.和结构体相比,Swift 的类支持实现继承,(受限的)反射,析构函数和多所有者. 既然类比结构体强大这么多,为什么还要使用结构体 ...

  3. 在Swift中应用Grand Central Dispatch(下)

    在第一部分中, 你学到了并发,线程以及GCD的工作原理.通过使用dispatch_barrrier和dispatch_sync,你做到了让 PhotoManager单例在读写照片时是线程安全的.除此之 ...

  4. Swift 中范围和区间如何使用?

    虽然现在swift语言已经发展到了2.0版了,但是相信很多学习iOS开发的童鞋仍对swift语言存在各种各样的疑问,今天小编将为大家详细介绍swift中的范围和区间,下面我们一起来看看吧. Range ...

  5. Swift中使用构建配置来支持条件编译-b

    在Objective-C中,我们经常使用预处理指令来帮助我们根据不同的平台执行不同的代码,以让我们的代码支持不同的平台,如: 1 2 3 4 5 6 7 8 9 #if TARGET_OS_IPHON ...

  6. 在Swift中使用遗留的C API

    Swift的类型系统的设计目的在于简化我们的生活,为此它强制用户遵守严格的代码规范来达到这一点.毫无疑问这是一件大好事,它鼓励程序员们编写 更好更正确的代码.然而,当Swift与历史遗留的代码库.特别 ...

  7. Swift中的设计模式

    设计模式(Design Pattern)是 对软件设计中普遍存在的各种问题,所提出的解决方案.这个术语是由埃里希·伽玛等人(Erich Gamma,Richard Helm,Ralph Johnson ...

  8. 如何在 Swift 中优雅地处理 JSON

    阅读目录 在Swift中使用JSON的问题 开始 基础用法 枚举(Enumeration) 下标(Subscripts) 打印 调试与错误处理 后记   因为Swift对于类型有非常严格的控制,它在处 ...

  9. Swift 中 String 取下标及性能问题

    Swift 中 String 取下标及性能问题 取下标 String String 用 String.Index 取下标(subscript)得到 Character,String.Index 要从 ...

随机推荐

  1. pomelo 服务器之间的通信

    master服务器在启动的时候会启动mater服务,生成一个MasterAgent,作为中心服务器. 然后所有服务器,包括mater服务器,都会启动monitor服务,生成一个MonitorAgent ...

  2. memcached的基本命令(安装、卸载、启动、配置相关)

    memcached的基本命令(安装.卸载.启动.配置相关):-p 监听的端口 -l 连接的IP地址, 默认是本机  -d start 启动memcached服务 -d restart 重起memcac ...

  3. UITableView类用法大全:UITableView属性

    [storyboard创建tableView步骤] 1.设置根视图 2.选中视图,设置导航栏editor/embed in/navigationcontroller 3.cell设置Identifie ...

  4. soapUI的使用

    首先下载soapUI下载地址在网上能够搜的到  windows下载这个soapUI-x32-3_5.exe(中间的数字是版本,能够下载最新的,这个已经有了JMS的測试功能)  首先得有一个webser ...

  5. OpenCV与QT联合编译 分类: Eye_Detection ZedBoard OpenCV shell ubuntu 2014-11-08 18:54 143人阅读 评论(0) 收藏

    问题1:首先参考rainysky的博客,发现qmake时发生找不到目录,文件的错误,又找不到 qmake.conf 文件的写法.所以开始按照网上的程序修改 XXX.pro 文件. 问题2:使用QT C ...

  6. java继承分析

    把java学完之后有開始了一遍突然发现对于继承还是不太理解所以就做了一个測试来分析一下 <span style="font-size:18px;">class A{ p ...

  7. oracle:变长数组varray,嵌套表,集合

    创建变长数组类型 ) );  这个变长数组最多可以容纳两个数据,数据的类型为 varchar2(50) 更改元素类型的大小或精度 可以更改变长数组类型和嵌套表类型 元素的大小. ALTER TYPE ...

  8. 第一篇:python基础

    python基础   python基础 本节内容 python起源 python的发展史 为什么选择python3 第一个python程序 变量定义 表达式和运算符 用户输入 流程控制 判断 流程控制 ...

  9. mysql 安装-编码

    mysql的安装过程相对较为简单,在这里就不阐述,我想说的问题是,关于编码的安装, 在安装到达'Please select the default character set'的时候,选择'Manul ...

  10. memcached和mongodb 在windows下安装

    要在新机器上安装memcached和mongodb服务,折腾了一天,终于把这两个服务在windows下跑起来了. memcached主要参考http://www.rootop.org/pages/27 ...