Xcode: Running Logic and Application Tests form command line.

There are at least three very important sources of information:

  1. http://longweekendmobile.com/2011/04/17/xcode4-running-application-tests-from-the-command-line-in-ios/
  2. http://blog.carbonfive.com/2011/04/06/running-xcode-4-unit-tests-from-the-command-line/
  3. http://www.raingrove.com/2012/03/28/running-ocunit-and-specta-tests-from-command-line.html

Having said that, here some additional hints.

  1. It does not really matter if you use schemes with workspaces (or without workspaces) or you decide to use targets. Both will work just fine.
  2. iPhone Simulator will start regardless of the kind of testing you are doing. It will start with logic tests and it will start with application tests. The difference is that with logic tests it does not run your app and so you have no access to the application object. Also, the simulator window will not be brought to the foreground when running logic tests – therefore it will not be disruptive – just do not kill the simulator after each run, and then you will hardly notice its presence.
  3. Logic Tests are naturally supported from the command line. For Application Tests you will have to do something extra.

CLOSE YOUR iOS SIMULATOR BEFORE RUNNING THE COMMANDS BELOW!

Running Logic Tests from command line

Assuming your logic test target has name LogicUnitTests, the command to run your logic tests is:

xcodebuild -target LogicUnitTests -configuration Debug -sdk iphonesimulator5.1 TEST_AFTER_BUILD=YES clean build

The TEST_AFTER_BUILD=YES option option is only needed if you do not have Test After Build option set to Yes in the Unit Testing group in your target’s Build Settings. If you like schemes and workspaces, the same effect will be achieved with the following command:

xcodebuild -workspace MyWorkspace.xcworkspace -scheme LogicUnitTests -sdk iphonesimulator5.1 -configuration Debug TEST_AFTER_BUILD=YES  clean build

Running Application Tests from command line

As mentioned above, Application Tests are not natively supported by malicious people from Apple. So to make it work in Xcode 4.3.2 you have to do the following first:

  1. Got to your Applications folder, locate Xcode, right click and choose Show Package Contents.
  2. Locate the file: /Applications/Xcode.app/Contents/Developer/ Platforms/iPhoneSimulator.platform/ Developer/Tools/RunPlatformUnitTests 3. In the root of your project create folder XcodeScripts and copy the file located above to this folder.
  3. Change line 95 from:

    Warning ${LINENO} "Skipping tests; the iPhoneSimulator platform does not currently support application-hosted tests (TEST_HOST set)."
    

    to:

    export OTHER_TEST_FLAGS="-RegisterForSystemEvents" RunTestsForApplication "${TEST_HOST}" "${TEST_BUNDLE_PATH}" 
    

    and…save the file.

  4. In your Application Tests target’s Build Phases tab, got to Run Script phase and change the command from:

    "${SYSTEM_DEVELOPER_DIR}/Tools/RunUnitTests"
    

    to:

    "${PROJECT_DIR}/XcodeScripts/RunPlatformUnitTests"
    

After all those steps you can now run your Application Tests with the following command:

xcodebuild -target ApplicationUnitTests -configuration Debug -sdk iphonesimulator5.1 TEST_AFTER_BUILD=YES clean build

Or, if you insist on using schemes and workspaces:

xcodebuild -workspace MyWorkspace.xcworkspace -scheme ApplicationUnitTests -sdk iphonesimulator5.1 -configuration Debug TEST_AFTER_BUILD=YES clean build

What is interesting for me, and maybe it can be a positive surprise, is that the iPhone Simulator will not be started (at least without GUI). I was a bit scared that maybe my application tests are not run as logic tests, but it does not seem so. My application objects is accessible and view are perfectly constructed. The following code should not fail if your test is run as an application test:

UIApplication *application = [UIApplication sharedApplication];
STAssertNotNil(application,@"application is nil!");
AppDelegate *appDelegate = [application delegate];
STAssertNotNil(appDelegate,@"appDelegate is nil!");
UIWindow *window = [appDelegate window];
STAssertNotNil(window,@"window is nil!");
self.vc = (ViewController*)[window rootViewController];

Do not forget to adjust the view controller and the application delegate classes to the ones you use in your project.

Tags: , , , , , , , ,

4 Responses to “Xcode: Running Logic and Application Tests form command line.”

  1. Thanks for the post. This is an ongoing problem that I wish Apple would fix.

    One thing I noticed is that often the tests fail if the simulator is already open. I ended up adding a little Applescript to my Makefile that kills the simulator immediately before running the application unit tests (logic unit tests seem fine as you say). I wrote it up http://www.stewgleadow.com/blog/2012/02/09/running-ocunit-and-kiwi-tests-on-the-command-line/

    It sounds like you don’t have much love for schemes. Is there a reason for that? While fiddly, I’ve found for complex build dependencies they work a lot better than building the targets – especially from the command line. I prefer everything in the derived data directory for the workspace than in individual local build directories for each target.

    • marcin.czenko says:

      You are absolutely right. Workspaces and schemes are absolutely great and I learning more and more them :) . The original blog post about running tests from command line were mentioning both solutions, so I decided to follow the same path. I must sound ironic the way I am writing about schemes: that’s just me…
      I will have to look at your blog, I tried Kiwi time ego, just after ARC was introduced and at that time it did not work for me. I have to retry soon.
      Thanks for you comment.

  2. informatimago says:

    With Xcode4, it doesn’t work. And neither does it work to set TEST_AFTER_BUILD as an environment variable.

    /usr/bin/xcodebuild -project “XYZ.xcodeproj” -sdk “macosx10.7″ -configuration debug -target TEST_AFTER_BUILD=YES all-test
    Build settings from command line:
    SDKROOT = macosx10.7

    xcodebuild: error: The project ‘XYZ.xcodeproj’ does not contain a target named ‘TEST_AFTER_BUILD=YES’.
    make: *** [tests] Error 65

Leave a Reply