Tutorial: Getting KIF to Work in Your Swift Project

KIF is a BDD-enabling UI test tool for CocoaTouch projects. I use it to do automated sanity checks on the behavior of my app, as an adjunct to driving out most of my app logic with unit tests.

I’ve found Xcode 6, iOS 8, and Swift to be tough on some of my favorite tools (I can’t even get Specta to build!), but most of what those tools do for me can still be covered, even if in a somewhat clunky fashion, by XCUnit. Achieving the power and brevity of KIF’s UI testing capabilities in XCUnit, though, is quite a stretch. Fortunately, I was able to get KIF up and running, and it didn’t take a ton of work.

First, I got CocoaPods working. Some people have found it tricky to make that happen with Xcode 6, but the necessary workarounds are amply covered on StackOverflow and elsewhere.

Second, I added the following to my Podfile:

(Note that I created a separate test target for my UI tests – UI tests can take a long time to run, and I don’t want them to slow me down to the point of distraction when I’m iterating rapidly on unit tests. I arrange these test targets in separate schemes that I switch between based on whether I’m working on the UI or at a lower level at the moment. The main scheme still runs both tests targets, mainly for CI purposes.)

The last step to compiling in KIF, of course, is to #import <KIF/KIF.h> in a bridging header – if you’re not sure how to do that, check out Step 4 of my last tutorial – it’s pretty simple.

Then came the problem: I can’t just write my tests like I’m used to. The idiomatic KIF 3.0 syntax for a UI test in Objective-C looks something like:

You’d think that that would translate to something like this in Swift:

Sadly, no. Swift can’t find tester. When you dig into it, you’ll find that tester has the following definition

…and as you may have heard, Swift has a problem with #define in bridged Objective-C code.

It gets worse, too: KIFActorWithClass is also a #define, and the whole unpacked expression is pretty ugly. And I just want to use tester in my code, like I did in Objective-C. (Yes, I know, I could just suck it up and write my tests in Objective-C – LIKE AN ANIMAL – but I’m trying to learn Swift here.)

My solution was to dig into the #define bits, and massage what I found into Swift code. I may refine this further (by pulling that computed property into a KIFTestCase extension, for starters), but this got me up and running:

And… disco!

I’m looking forward to a deep dive on testing in Swift – if you have any tips to share, let me know in the comments!

  7 comments for “Tutorial: Getting KIF to Work in Your Swift Project

  1. June 24, 2014 at 14:48

    I’m having troubles settings up KIF in xcode 6 beta 2. I Pods can’t compile KIF since the path to the frameworks is set to: /Applications/Xcode6-Beta2.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.1.sdk/System/Library/Frameworks/CoreGraphics.framework (http://www.m-i-u.de/images-i84081bpzhoz.png). It applies to all Frameworks created by Pod (CoreGraphics, Foundation, XCTest).
    Can I set the path of these manually? I’m quite new to Pods.

    Looking forward to hearing from you 🙂

    – Matteo

  2. June 24, 2014 at 16:57

    6b2 has screwed up everything for me. Can’t build with any CocoaPods, debugger is borked, outlets are acting funny… I’m ready for beta 3 any time now.

  3. Alby
    October 31, 2014 at 06:28

    Hi Can you give an example on testing outlets and ibactions?

  4. Me
    January 8, 2015 at 15:44

    What does KIF give you that the built in Xcode 6 testing framework does not?

  5. January 8, 2015 at 17:10

    Great question. It gives you a rich set of tools for interacting with the UI in ways that a user would. Additionally, it’s in Objective-C, not Javascript like UI Automation. And since it’s in Objective-C and baked into the test target (and this is the cherry on top), you can reach under the hood and set the state of NSUserDefaults or the app keychain or the filesystem or the Core Data database as part of your testing.

Leave a Reply

Your email address will not be published. Required fields are marked *