Skip to content

Getting Started with Kiwi 2.0

Tyler Tape edited this page Apr 14, 2014 · 45 revisions

This guide is the starting point for learning how to use Kiwi in iOS and OS X projects. The goal of this guide (and Kiwi) is to set up a workspace where you are able to test your application code as simply as running or profiling your application would be.

Requirements:

Xcode iOS OS X
4.5+ 5.0+ 10.7+

Step -1: CocoaPods

If you already have CocoaPods installed, skip this step.

In modern iOS and OS X development, you inevitably end up using open source libraries (e.g. AFNetworking) in your projects. This results in additional complexity in library management. CocoaPods makes this less painful and is our preferred library management tool.

  1. Install CocoaPods:

    $ [sudo] gem install cocoapods
    $ pod setup
  2. If you're still using a version of Xcode prior to Xcode 5, you'll need to make sure Xcode tools are usable from the command line. Open up Xcode and install or make sure Command Line Tools are installed:

    Preferences -> Downloads -> Components -> Command Line Tools -> Install

Step 0: Setting Up a Unit Test Target

If your project already has a Unit Test Target, skip this step.

Before adding Kiwi to your project, you need a Unit Test Target that is run by Xcode during testing. If you're using Xcode 5, this unit test target is included by default when you create a new project. Otherwise, check the "Add Unit Tests" option in the project wizard when creating your project, or manually add a Unit Test Target.

Select the project in the Project Navigator and observe the targets of the project. If there is already a Unit Test Target, skip this step. Otherwise, we need to add one.

Unit Test Target might already exist If not, add a Unit Test Target
getting-started-with-2 0-targetexists getting-started-with-2 0-addingtarget
  1. Select the project in the Project Navigator.

  2. Add a "Cocoa Touch Unit Testing Bundle" to the project:

    File -> New -> Target... -> Other -> Cocoa Touch Unit Testing Bundle
  3. Give your Unit Test Target an appropriate name (e.g. "AmazingAppTests"). Make sure the "Project" setting accurately reflects the project you want to test and click "Finish".

The Unit Test Target should now be in your project. Remember the name of your Unit Test Target ("AmazingAppTests" above) before moving on.

Step 1: Installing Pods

The next step is creating or updating the Podfile for your project. It describes what libraries CocoaPods will be managing for you. To get Kiwi installed, we will add an entry for Kiwi in the file.

  1. First, close Xcode. You'll be reopening the project later.

  2. Create a new file named Podfile in the directory that contains the your .xcodeproj file, or edit it if it already exists. Adapt the Podfile to look like below. Make sure to use the target name from the previous step.

    # Podfile
    
    # Select the appropriate platform below
    # Specify the minimum supported iOS version (or later) required by Kiwi
    platform :ios, '5.0'
    # platform :osx
    
    #
    # Some other entries might already exist in the file
    # ...
    #
    
    # Add Kiwi as an exclusive dependency for the AmazingAppTests target
    target :AmazingAppTests, :exclusive => true do
      pod 'Kiwi'
    end

    If you're using Xcode 5 with a brand new project (XCTest based instead of OCUnit based) use this instead:

    target :AmazingAppTests, :exclusive => true do
      pod 'Kiwi/XCTest'
    end
  3. Install your project's pods. CocoaPods will then download and configure the required libraries for your project:

    $ pod install
  4. Heed the advice CocoaPods provides you. Henceforth, you shall use the .xcworkspace file to work on your project:

    $ open myproject.xcworkspace

Step 2: Unit Test Target Configuration

This part is tricky. Read carefully.

The goal of this step is to ensure that (i) the Unit Test Target can be built correctly, and (ii) the built Unit Test Target is loaded and injected correctly into the application executable when running tests.

Before moving on, lets talk about the Unit Test Target for a second. The way Kiwi works is that you write tests (also called specs) that test your application code. Your application code (such as .m files) will be built in your application target, while your tests should be built in your Unit Test Target. Consequently, make sure that all test files you create are added to the Unit Test Target.

All the steps below refer to both "Debug" and "Release" configurations where relevant.

  1. Open up the .xcworkspace file if you haven't already from the previous step. Observe the Pods-<TargetName>.xcconfig file in your project. This file is generated by CocoaPods and contains build settings to be used specifically for the Unit Test Target.
  2. Select the project in the Project Navigator (do not select the Unit Test Target) then select the "Info" tab. Notice the "Configurations" section, expanding it if needed, then expand the "Debug" and "Release" sections below it.
  3. Ensure that Pods-<TargetName>.xcconfig is shown in the Unit Test Target in all configurations. Once this is set, the Unit Test Target should be picking up configurations settings from the xcconfig file.
  4. Select the Unit Test Target and then select the "Build Settings" pane.
  5. Ensure that "Other Linker Flags" contains -ObjC -framework SenTestingKit. This (i) links the binary against SenTestingKit and (ii) ensures that Kiwi's symbols are not stripped from the binary when built because the linker thinks that they are unused by other code. (Note: Under Xcode 5, this will read -ObjC -framework XCTest instead.)
  6. Replace "MyProject" below with the case-sensitive name of your application project, and "ApplicationTargetName" with the case-sensitive name of your application target (by default, this is the same name as the application project). This step specifies that the application executable will be used to load the unit test bundle when tests are run. (Note that this step is not necessary if your target is a static library – you can leave this field blank.)
  • iOS: Ensure that "Bundle Loader" is set to $(BUILT_PRODUCTS_DIR)/MyProject.app/ApplicationTargetName.
  • OS X: Ensure that "Bundle Loader" is set to $(BUILT_PRODUCTS_DIR)/MyProject.app/Contents/MacOS/ApplicationTargetName.
  1. Ensure that "Test Host" is is set to $(BUNDLE_LOADER). This specifies the executable that the unit tests will be injected into. We make it match the value of the "Bundle Loader" setting. (Note that this step is not necessary if your target is a static library – you can leave this field blank.)

Step 3: Schemes

Also tricky.

Lets revisit the goal of this whole endeavor - we want to set up our workspace so that we are able to test our application code with as little fuss as possible. If you've performed the previous steps correctly, you should now have a building Unit Test Target with a set of tests that are run while testing. But how exactly do we get to this testing phase?

Xcode uses something called a "Scheme" to figure out what targets to build and settings to use when building and running a product. Schemes can be added and configured in a multitude of fashions so we will focus here on the simplest case that can be adapted to most environments.

  1. Open the Scheme Management window:

    Product -> Scheme -> Manage Schemes...

    I'm going to be frank. I have no idea what you are going to see here - depending on the Create Your Own Adventure path you used to get here, there may be one or several schemes listed here. Luckily, we have a clear goal. We want to modify the scheme used to run our application to have a "Test" action that uses our Unit Test Target.

  2. Select the scheme that corresponds to the one you are using to run your application. If you do not understand the meaning of this, then select the scheme that is named the same as your project. If no such scheme exists, then ... guess. Really. And then email me.

  3. Edit the scheme:

    Edit ...
  4. Select the "Test" action on the left side pane.

  5. Ensure that your Unit Test Target is listed and checked in the "Tests" listing. Use the + button to add it here if it does not show up.

Done and done!

Step 4: Write a Test

We can finally get down to the business of writing actual tests. This is the step you will repeat when writing tests for different parts of your application. We will create a trivial test case to make sure everything is set up correctly.

  1. Right click your project and add a new test case to the project:

    # iOS
    New File... -> Cocoa Touch -> Objective-C test case class
    # OSX
    New File... -> Cocoa -> Objective-C test case class
  2. Name the class SampleSpec and select "Next".

  3. Make sure that only the Unit Test Target is checked and then select "Create". This makes it so that the code for the test only exists in the Unit Test Target and not your application.

  4. Delete the .h file that Xcode generated automatically. You can also move the .m file somewhere else as your heart desires.

  5. Open .m file and replace the contents with below:

    #import "Kiwi.h"
    
    SPEC_BEGIN(MathSpec)
    
    describe(@"Math", ^{
        it(@"is pretty cool", ^{
            NSUInteger a = 16;
            NSUInteger b = 26;
            [[theValue(a + b) should] equal:theValue(43)];
        });
    });
    
    SPEC_END
  6. Make sure the scheme you set up in Step 3 above is selected in the run bar. If applicable, it is recommended you select the simulator for now. Time to run tests. Press Cmd-U (the default hotkey) or:

    Product -> Test
  7. Let Xcode go through its machinations and at some point your tests should run.After a short time, Xcode should report an error. Success! Xcode should also helpfully pop up the Issue Navigator (fourth tab in the left hand pane).

  8. Click on the single failure, which should open up the exact location of the problem in Xcode.

  9. Fix the error - if you need to ask how...

  10. Run the test again (step 6).

  11. The tests should run and Xcode should not report an error. Success!

You've successfully set up your environment to run tests for your application. Repeat this step to add tests for any aspect of your application that you want to have good feelings about.

Step 5: Next Steps

So you want to write tests?

With any luck, you now know enough to set up Kiwi tests in your projects. The next tough part is figuring out what and how to test without it being a waste of your time.

The Kiwi wiki will be expanded in the future with additional guides (feel free to contribute!). Until then, a great place to continue learning about proper testing is the Kiwi Book by Daniel Steinberg. The instructions about setup are slightly out of date, but the content is solid.

Feedback

For feedback, email allen@lentor.io.

Making a guide is tough work. The following people made it less tough:

  • chrishulbert
  • dimsumthinking
  • frosty
  • jeffremer
  • jonah-carbonfive
  • MaxGabriel
  • mneorr
  • shepting
  • sojinkim