Adding Test target to an existing project in Xcode

February 16, 2016

Adding Test target to an existing project in Xcode

I had a project, for which it was time to add Unit Tests. Since the project was originally created without any test target, I thought that it is going to be a piece of cake. I had never been so wrong before. In the end I spent 6 hours battling with errors that I was getting due to Cocoapods dependencies, but I finally made it work.

So here is a simple step-to-step guide that I think will be very useful for people who are going the same path.

Adding Test bundle itself

First of all just add new Target via File > New > Target... and select iOS Unit Testing Bundle. Done.

In case you mix Swift with Objective-C

To make everything work together, you need Bridging-Header.h file, which you very likely had already created. But to make it work with Test Bundle you need to make this one extra step, otherwise you will get funny errors:

Go to Test Budle target in your Project > MyAppNameTests > Build Settings > Objective-C Bridging Header and paste the same stuff you did in your main app target.

In case you use Cocoapods

Next I had Cocoapods and it was giving me a hard time, but luckily I found a way to calm it down - you need to edit your Podfile and add this:

link_with 'MyAppNameTests'

The way Cocoapods works you have to prove this line, which tells that you want to link Pods framework with your Test Bundle target as well, to get access to all those pods you have in there. Otherwise it just won't work.

Configuring Test Bundle

Now since we are done configuring our Cocoapods and Bridging Header, we need to actually configure the test bundle itself. All you need to do is:

  1. Click the Build Settings tab and set the Bundle Loader setting to this:
$(BUILT_PRODUCTS_DIR)/MyExistingApp.app/MyExistingApp
  1. Set the Test Host build setting to this:
$(BUNDLE_LOADER)
  1. Go back to app target (not the test target) and set the Symbols Hidden by Default build setting to this:
NO

Access to your classes from the Test target

Now since Swift 2 we have a super easy way to get access to all your classes and structs and other stuff with new @testable attribute. So basically, edit your TestCases like this, before you start, :

import XCTest
@testable import MyAppName

final class MyFirstTest: XCTestCase {

    override func setUp() {
        super.setUp()
    }

    override func tearDown() {
        super.tearDown()
    }

    func testExample() {

    }

}

Aaaaaand you are done and you have just saved yourself couple of hours of your precious life.

Comments

comments powered by Disqus