Contents

kif-framework/kif

**IMPORTANT! Even though KIF is used to test your UI, you need to add it to your Unit Test target, _not_ your UI Test target. The magic of KIF is that it allows you to drive your UI from your unit tests and reap all the advantages of testing in-process.**

Example test cases

With your project configured to use KIF, it's time to start writing tests. There are two main classes used in KIF testing: the test case (KIFTestCase, subclass of XCTestCase) and the UI test actor (KIFUITestActor). The XCTest test runner loads the test case classes and executes their test. Inside these tests, the tester performs the UI operations which generally imitate a user interaction. Three of the most common tester actions are "tap this view," "enter text into this view," and "wait for this view." These steps are included as factory methods on KIFUITestActor in the base KIF implementation.

KIF relies on the built-in accessibility of iOS to perform its test steps. As such, it's important that your app is fully accessible. This is also a great way to ensure that your app is usable by everyone. Giving your views reasonable labels is usually a good place to start when making your application accessible. More details are available in Apple's Documentation.

The first step is to create a test class to test some functionality. In our case, we will create a login test (LoginTests). Create a new class that inherits from KIFTestCase. You may have to update the import to point to <KIF/KIF.h>. The test method name provides a unique identifier. Your KIFTestCase subclass should look something like this:

LoginTestCase.h

#import <KIF/KIF.h>

@interface LoginTests : KIFTestCase
@end

LoginTestCase.m

#import "LoginTests.h"
#import "KIFUITestActor+EXAdditions.h"

@implementation LoginTests

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

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

- (void)testSuccessfulLogin
{
    [tester enterText:@"user@example.com" intoViewWithAccessibilityLabel:@"Login User Name"];
    [tester enterText:@"thisismypassword" intoViewWithAccessibilityLabel:@"Login Password"];
    [tester tapViewWithAccessibilityLabel:@"Log In"];

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

@end

Most of the tester actions in the test are already defined by the KIF framework, but -navigateToLoginPage and -returnToLoggedOutHomeScreen are not. These are examples of custom actions which are specific to your application. Adding such steps is easy, and is done using a factory method in a category of KIFUITestActor, similar to how we added the scenario.

KIFUITestActor+EXAdditions.h

#import <KIF/KIF.h>

@interface KIFUITestActor (EXAdditions)

- (void)navigateToLoginPage;
- (void)returnToLoggedOutHomeScreen;

@end

KIFUITestActor+EXAdditions.m

#import "KIFUITestActor+EXAdditions.h"

@implementation KIFUITestActor (EXAdditions)

- (void)navigateToLoginPage
{
    [self tapViewWithAccessibilityLabel:@"Login/Sign Up"];
    [self tapViewWithAccessibilityLabel:@"Skip this ad"];
}

- (void)returnToLoggedOutHomeScreen
{
    [self tapViewWithAccessibilityLabel:@"Logout"];
    [self tapViewWithAccessibilityLabel:@"Logout"]; // Dismiss alert.
}

@end

Everything should now be configured. When you run the integration tests using the test button, ⌘U, or the Xcode Test Navigator (⌘5).

Use with other testing frameworks


KIFTestCase is not necessary for running Tests. Tests can run directly in XCTestCase or any subclass. The basic requirement is that when you call tester or system, self must be an instance of XCTestCase and you must call KIFEnableAccessibility in setUp.

For example, the following Specta test works without any changes to KIF or Specta:

#import <Specta.h>
#import <KIF.h>

SpecBegin(App)

describe(@"Tab controller", ^{

  it(@"should show second view when I tap on the second tab", ^{
    [tester tapViewWithAccessibilityLabel:@"Second" traits:UIAccessibilityTraitButton];
    [tester waitForViewWithAccessibilityLabel:@"Second View"];
  });

});

SpecEnd

If you want to use KIF with a test runner that does not subclass XCTestCase, your runner class just needs to implement the KIFTestActorDelegate protocol which contains two required methods.

- (void)failWithException:(NSException )exception stopTest:(BOOL)stop; - (void)failWithExceptions:(NSArray )exceptions stopTest:(BOOL)stop;

In the first case, the test runner should log the exception and halt the test execution if stop is YES. In the second, the runner should log all the exceptions and halt the test execution if stop is YES. The exceptions take advantage of KIF's extensions to NSException that include the lineNumber and filename in the exception's userData to record the error's origin.

Use with Swift

Since it's easy to combine Swift and Objective-C code in a single project, KIF is fully capable of testing apps written in both Objective-C and Swift.

If you want to write your test cases in Swift, you'll need to keep two things in mind.

  1. Your test bundle's bridging header will need to #import <KIF/KIF.h>, since KIF is a static library and not a header.
  2. The tester and system keywords are C preprocessor macros which aren't available in Swift. You can easily write a small extension to XCTestCase or any other class to access them:
extension XCTestCase {
    func tester(file : String = #file, _ line : Int = #line) -> KIFUITestActor {
        return KIFUITestActor(inFile: file, atLine: line, delegate: self)
    }

    func system(file : String = #file, _ line : Int = #line) -> KIFSystemTestActor {
        return KIFSystemTestActor(inFile: file, atLine: line, delegate: self)
    }
}

extension KIFTestActor {
    func tester(file : String = #file, _ line : Int = #line) -> KIFUITestActor {
        return KIFUITestActor(inFile: file, atLine: line, delegate: self)
    }

    func system(file : String = #file, _ line : Int = #line) -> KIFSystemTestActor {
        return KIFSystemTestActor(inFile: file, atLine: line, delegate: self)
    }
}

See Documentation/Examples/Testable Swift for sample code.

Troubleshooting


Simulator launches but app doesn't appear, steps time out after 10 seconds

This issue occurs when XCTest does not have a valid Test Host. Reread the instructions above with regards to the "Bundle Loader" and "Test Host" settings. You may have missed something.

Step fails because a view cannot be found

If KIF is failing to find a view, the most likely cause is that the view doesn't have its accessibility label set. If the view is defined in a xib, then the label can be set using the inspector. If it's created programmatically, simply set the accessibilityLabel attribute to the desired label.

If the label is definitely set correctly, take a closer look at the error given by KIF. This error should tell you more specifically why the view was not accessible. If you are using -waitForTappableViewWithAccessibilityLabel:, then make sure the view is actually tappable. For items such as labels which cannot become the first responder, you may need to use -waitForViewWithAccessibilityLabel: instead.

Unrecognized selector when first trying to run

If the first time you try to run KIF you get the following error:

2011-06-13 13:54:53.295 Testable (Integration Tests)[12385:207] -[NSFileManager createUserDirectory:]: unrecognized selector sent to instance 0x4e02830 2011-06-13 13:54:53.298 Testable (Integration Tests)[12385:207] * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSFileManager createUserDirectory:]: unrecognized selector sent to instance 0x4e02830'

or if you get another "unrecognized selector" error inside the KIF code, make sure that you've properly set the -ObjC flag as described above. Without this flag your app can't access the category methods that are necessary for KIF to work properly.

Continuous Integration


A continuous integration (CI) process is highly recommended and is extremely useful in ensuring that your application stays functional. The easiest way to do this will be with Xcode, either using Bots, or Jenkins or another tool that uses xcodebuild. For tools using xcodebuild, review the manpage for instructions on using test destinations.

Contributing


We're glad you're interested in KIF, and we'd love to see where you take it.

Any contributors to the master KIF repository must sign the Individual Contributor License Agreement (CLA). It's a short form that covers our bases and makes sure you're eligible to contribute.

When you have a change you'd like to see in the master repository, send a pull request. Before we merge your request, we'll make sure you're in the list of people who have signed a CLA.

Thanks, and happy testing!

Package Metadata

Repository: kif-framework/kif

Default branch: master

README: README.md