Skip to content

Why KIF Quick

Paul Zabelin edited this page Dec 26, 2016 · 9 revisions

Why we made KIF-Quick

tldr; UI testing in Swift using BDD

It's a natural integration of two technologies: http://stackoverflow.com/a/41327012/7341239

For our UI integration tests we use KIF framework. Why we choose KIF is better explained in this blog post by LinkedIn Engineering: UI Automation: Keep it Functional – and Stable!

At the same time we are developing in Swift and write our unit tests in Swift. Actually we are using Quick and Nimble frameworks to help us with that. Quick is a behavior-driven development framework for Swift inspired by RSpec. See this blog post introducing Quick: Unit Testing in Swift: A Quick Look at Quick

Using BDD specs for testing gives us better readable specifications with nested contexts. That's exactly what KIF-Quick enables for our user tests. UI tests benefit even more from BDD style then unit tests as our domain specific language is shared beyond the development. See this great article on Behavior-driven development on Wikipedia.

Examples

Compare two examples of tests for app login below. First one is using KIF-Quick and another one regular XCTest.

KIF Spec using Quick BDD syntax in Swift

import Quick
import KIF_Quick

class LoginSpec: KIFSpec {
    override func spec() {
        describe("successful login") {
            context("home view") {
                beforeEach() {
                    tester().navigateToLoginPage()
                }

                it("should open Welcome page") {
                    viewTester().usingLabel("Login User Name").enterText("[email protected]")
                    viewTester().usingLabel("Login Password").enterText("thisismypassword")
                    viewTester().usingLabel("Log In").tap()
                    viewTester().usingLabel("Welcome").waitForView()
                }

                afterEach() {
                    tester().returnToLoggedOutHomeScreen()
                }
            }
        }
    }
}

KIF Test in Objective-C

#import "LoginTests.h"

@implementation LoginTests

- (void)beforeEach
{
    [tester navigateToLoginPage];
}

- (void)afterEach
{
    [tester returnToLoggedOutHomeScreen];
}

- (void)testSuccessfulLogin
{
    [tester enterText:@"[email protected]" intoViewWithAccessibilityLabel:@"Login User Name"];
    [tester enterText:@"thisismypassword" intoViewWithAccessibilityLabel:@"Login Password"];
    [tester tapViewWithAccessibilityLabel:@"Log In"];

    // Verify that the login succeeded
    [tester waitForTappableViewWithAccessibilityLabel:@"Welcome"];
}

@end

as you can see from above two examples first offers more readable syntax and especially useful in organizing multiple contexts.