Xcode4: Running Application Tests From The Command Line in iOS
By Mark on April 17th, 2011 in TechnobabbleTags: dev, ios4, unit testing, xcode
While researching the “is GHUnit still relevant vis-a-vis Xcode 4” article, I discovered this Carbon Five post by Jonah: Running Xcode 4 unit tests from the command line.
In short, I found a way to run iOS application unit tests from the command line; this article describes that process.
Part of the research is about automation – how well GHUnit and/or OCUnit test suites can be automated.
In my book, command line = automation. Last summer I installed Hudson CI on Paul’s Mac Mini and started automated builds. Why not add unit tests to the mix?
Jonah’s post explains how to make a unit test bundle testable from the command line. Unfortunately, and he notes it as well, it only works for logic tests (e.g. no application tests). His approach uses schemes in Xcode 4.
Jonah’s command:
xcodebuild -workspace workspaceName.xcworkspace -scheme logicTestSchemeName -sdk iphonesimulator4.3 -configuration Debug clean build
I’m still not sure I fully understand schemes/workspaces yet, as they are new to Xcode 4, but this is definitely one case where good ol’ targets appear to work better.
By using the target paradigm, we can build the bundle without creating a new scheme. Instead, just use the test bundle’s name as your build target:
xcodebuild -target unitTestBundleTargetName -configuration Debug -sdk iphonesimulator4.3 clean build
This improved upon the first half of his post – removing the need to create a separate scheme. His post ends with a challenge for application tests:
In case it is of any help to other developers struggling with the difference between command line and Xcode builds.
The “Run Script” build phase of a unit test build target just runs… (edit: references some scripts, omitted for brevity)
Hopefully it will prove possible to use these scripts to match the behavior seen when running tests from within Xcode to automatically run application tests.
So, I included an application test in my unit test bundle, and this was the output:
/Developer/Platforms/iPhoneSimulator.platform/Developer/Tools/RunPlatformUnitTests:94: warning: Skipping tests; the iPhoneSimulator platform does not currently support application-hosted tests (TEST_HOST set).
Isn’t it supported? We’ve seen it working in Xcode 4. Maybe it really is supported, but Apple hasn’t updated the testing script because they were so busy just trying to get Xcode 4 in a semi-releasable state (highly likely). Or, it hasn’t been “officially” said to work; e.g. they don’t want to support it yet, so they’re not letting us do it.
After snaking through all the script calls, I found the culprit.
Change line 95 of /Developer/Platforms/iPhoneSimulator.platform/Developer/Tools/RunPlatformUnitTests from
Warning ${LINENO} "Skipping tests; the iPhoneSimulator platform does not currently support application-hosted tests (TEST_HOST set)."
to these 2 lines:
export OTHER_TEST_FLAGS="-RegisterForSystemEvents"
RunTestsForApplication "${TEST_HOST}" "${TEST_BUNDLE_PATH}"
The first line of code seems to make event handling work with Springboard (see comments below). The second line of code I stole from /Developer/Tools/RunPlatformUnitTests. Seems like it’s the default behavior for other platforms, just not the simulator SDK.
After inserting those lines, your tests should run (I’ve included a sample project with the set up to show the code, it is the “navigation based app” template using Core Data).
Also, it’s important to note that the Simulator will not run 2 instances. You’ll need to shut the Simulator if you have it open.
DISCLAIMER:Yes, I’m asking you to change your /Developer directory. You probably should back everything up, blah blah blah, and I don’t want to be blamed if you have to reinstall Xcode 4.
Also, I originally had Core Data as part of the project, but I was getting an NSCocoaErrorDomain error from my application on the console. After I removed Core Data from the project, the problem went away.
Deniz Demir helped me out there – a little Google brought up his post from late March, where he explained his troubles with Core Data and unit testing. Applying his fix inre: the documents directory makes my code work. Glad to see everyone work at the coal face of the problem!
Best of luck!





21 Responses to “Xcode4: Running Application Tests From The Command Line in iOS”
Mark Wotton says:
I’m having some trouble setting this up, even with your sample app.
This is with Xcode 4.0: after running
xcodebuild -target CmdlineAppTestingTests -configuration Debug -sdk iphonesimulator4.3 clean build
Run unit tests for architecture ‘i386′ (GC OFF)
/Developer/Tools/RunPlatformUnitTests.include:419: note: Running tests for architecture ‘i386′ (GC OFF)
2011-04-21 16:29:06.533 otest[18816:903] The test bundle at /fast/projects/foo2/CmdlineAppTesting/build/Debug-iphonesimulator/CmdlineAppTestingTests.octest could not be loaded because a link error occurred. It is likely that dyld cannot locate a framework framework or library that the the test bundle was linked against, possibly because the framework or library had an incorrect install path at link time.
/Developer/Tools/RunPlatformUnitTests.include:448: error: Failed tests for architecture ‘i386′ (GC OFF)
Apr 21, 2011 | Reply
Mark says:
Mark,
Hrm. Not sure what that issue is. I am using Xcode 4.0.1, but I highly doubt that’s the difference.
A dynamic linking issue… I guess let me have a look at it. Did you make any modifications to the sample project?
Apr 26, 2011 | Reply
Shaps says:
If I’m honest I was having trouble understanding how Unit Test are written. Like the kinds of tests I should be writing, how specific I should be. I was also unsure how to implement the Application Tests.
I finally came across your article and now have a much better understand of these things, especially after going through your sample project.
I really just wanted to say thank you for your posts, but mostly for your hilarious comments. For the record, I think its because Core Data likes Limp Bizkit too! Hahaha!
Apr 26, 2011 | Reply
Matthew Johnson says:
I made this change to my RunPlatformUnitTests file. The application unit tests work fine when run from Xcode, but they don’t work from the command line with xcodebuild. This is the command I’m using:
xcodebuild -target TestingTestsTests -configuration Debug -sdk iphonesimulator4.3 clean build
It hangs every time I try to run my application unit tests if I have iOS Simulator running before I run the tests. If I don’t have iOS Simulator running before I run the tests then I get the following error:
“Terminating since there is no system event server.
(Run the EventPump or pass the argument “-RegisterForSystemEvents” if you want to run without SpringBoard.”
My logic tests work fine if I remove the TEST_HOST build setting, but obviously that doesn’t help with application tests.
Any tips on what might be causing the issues I’m having? I’m eager to get application unit tests running from the command line.
Thanks!
May 5, 2011 | Reply
Mark says:
I should have included this in the post. The simulator NEEDS to be NOT running for all this to work.
May 8, 2011 | Reply
Matthew Johnson says:
To clarify, I did have the simulator closed prior to running this. Any further ideas?
May 13, 2011 | Reply
Mark says:
Matthew, I got it – for some reason when I first wrote this, OTHER_TEST_FLAGS must have been getting set explicitly. Not sure what changed (other than I upgraded to 4.0.2).
Now, I’ve added a second line into the script that sets it, so the tests should run now.
May 17, 2011 | Reply
Mark says:
@Mark Wotton – The only thing I can see from what you’ve pasted is that your script seems to be running in the wrong place. When I run it, I get:
/Developer/Tools/RunPlatformUnitTests.include:273: note: Running tests for architecture ‘i386′ (GC OFF)
That’s line 273, which is part of the function “RunApplicationTests” or something ( check it ). Your pasted comment seems to reference line 419, which is in the “RunBundleTests” or whatever function. I haven’t gone so far as yet to trace the scripting calls and see WHY that’s happening, but I reckon that’s the problem.
May 17, 2011 | Reply
Dave says:
Brilliant, just what I needed, thanks!
May 28, 2011 | Reply
Mandy says:
Hi, I managed to get the unit tests running without your hack of RunPlatformUnitTests. I just changed the Target Build Settings to remove the Test Host entry i.e. remove $(BUNDLE_LOADER). Not sure of the impact of this but it worked!
Nov 17, 2011 | Reply
Geoff says:
Hi Mandy, if you remove that test host entry then you can no longer run Application Tests, only Logic Tests
Nov 17, 2011 | Reply
Mark says:
Mandy & Geoff, thanks for the updated comments — someone said this the other day on StackOverflow — specifically that the hack is no longer necessary.
I need to set this up from scratch again on Xcode 4.2 and see if it is indeed the case. Watch for updates!
Nov 17, 2011 | Reply
Igor says:
How does this work for a device? With what arguments do you run the RunPlatformUnitTests?
Dec 17, 2011 | Reply
Dustin says:
Great post. Regarding the recent comments, I just went through this on a brand new project with Xcode 4.2 and the hack was still necessary. As mentioned above, you can change the build settings to accommodate logic tests but any application tests expecting NSApplication inside the simulator need this setup. I’ve tried to capture all the latest steps and how to detect if you’re inside a test for Core Data access (if necessary) from a Jenkins CI perspective if anyone needs it here:
http://lifeandcode.net/2011/12/automated-ios-jenkins-builds-with-application-tests-and-core-data/
Dec 19, 2011 | Reply
Scott Muc says:
Thanks so much for this post! This helped us get Kiwi tests running form the CLI. It’s a shame that it’s such a kludge to get this working.
Again, thanks for posting this. I believe this is the only post on the Internet that actually led us in the right direction.
Jan 6, 2012 | Reply
Mark says:
Scott,
Thanks. It feels good, I set out to “Solve A Problem”, and it worked
.
Jan 8, 2012 | Reply
Alec says:
This worked for me. Thanks so much… great post.
Feb 22, 2012 | Reply
Craig says:
This is great, it worked for me. The only problem is that the keychain doesn’t seem to work when running from the CLI. Any suggestions?
Feb 23, 2012 | Reply
Mark says:
Craig:
“security” is the command-line tool for dealing with the keychain. I assume you have certificate things you want to sort out.
Check out this SO post:
http://stackoverflow.com/questions/5525436/xcode-could-not-find-a-valid-private-certificate-valid-key-pair-for-this-profile
Feb 23, 2012 | Reply