How do I create application tests in a Cocoa Touch Unit Testing Bundle with Xcode 4?

6

I've created an Xcode 4 project with a Cocoa Touch Unit Testing Bundle. I'm able to create and run logic tests successfully. However, I'm not sure how to create a test as an application test that runs on an iOS device and uses UIKit. When I create a test that uses UIKit and try to run the tests in the bundle on the device, Xcode 4 pops up a dialog saying:

Logic Testing Unavailable

Logic Testing on iOS devices is not supported. You can run logic tests on the Simulator.

I tried running the test on the simulator, but of course it failed when making UIKit calls.

Does anyone know how to create and run application tests on iOS devices using Xcode 4 and a Cocoa Touch Unit Testing Bundle?

EDIT: In case it helps, here is the test code:

@implementation TinyWordsTests

- (void)setUp
{
    [super setUp];
    CC_DIRECTOR_INIT();
}

- (void)tearDown
{
    CC_DIRECTOR_END();
    [super tearDown];
}

- (void)testExample
{
    CCScene *scene = [TWOHelloWorldLayer scene];
    STAssertNotNil(scene, @"Scene must not be nil.");
}

@end

and the resulting stack trace from gdb when the test is run in the simulator:

(gdb) bt
#0  0x00464781 in __HALT ()
#1  0x003af8ed in _CFRuntimeCreateInstance ()
#2  0x00da81ea in GSFontCreateWithName ()
#3  0x038f55eb in UINewFont ()
#4  0x038f56bd in +[UIFont fontWithName:size:traits:] ()
#5  0x038f507d in +[UIFont fontWithName:size:] ()
#6  0x01a49205 in -[CCTexture2D(Text) initWithString:fontName:fontSize:] (self=0x197f9f0, _cmd=0xe10840, string=0x1a9c900, name=0x1a9c8f0, size=64) at CCTexture2D.m:487
#7  0x01a2d897 in -[CCLabelTTF setString:] (self=0x1981d70, _cmd=0x156e07, str=0x1a9c900) at CCLabelTTF.m:95
#8  0x01a2dc9d in -[CCLabelTTF initWithString:fontName:fontSize:] (self=0x1981d70, _cmd=0xe10840, str=0x1a9c900, name=0x1a9c8f0, size=64) at CCLabelTTF.m:79
#9  0x01a2da9a in +[CCLabelTTF labelWithString:fontName:fontSize:] (self=0x1a9b53c, _cmd=0xe0ddc0, string=0x1a9c900, name=0x1a9c8f0, size=64) at CCLabelTTF.m:53
#10 0x01a01b10 in -[TWOHelloWorldLayer init] (self=0x197ee40, _cmd=0x2c7c) at TWOHelloWorldLayer.m:39
#11 0x01a341bb in +[CCNode node] (self=0x1a99ee4, _cmd=0x3baad59) at CCNode.m:231
#12 0x01a01a80 in +[TWOHelloWorldLayer scene] (self=0x1a99ee4, _cmd=0xe00fa0) at TWOHelloWorldLayer.m:22
#13 0x01a5d430 in -[TinyWordsTests testExample] (self=0x197e490, _cmd=0xe59dd0) at TinyWordsTests.m:30
#14 0x00410c7d in __invoking___ ()
#15 0x00410b51 in -[NSInvocation invoke] ()
#16 0x201043d2 in -[SenTestCase invokeTest] ()
#17 0x20104aa7 in -[SenTestCase performTest:] ()
#18 0x201041d3 in -[SenTest run] ()
#19 0x20106eda in -[SenTestSuite performTest:] ()
#20 0x201041d3 in -[SenTest run] ()
#21 0x20106eda in -[SenTestSuite performTest:] ()
#22 0x201041d3 in -[SenTest run] ()
#23 0x201067a4 in +[SenTestProbe runTests:] ()
#24 0x000023c7 in ?? ()
#25 0x000025f2 in ?? ()
#26 0x0000209a in ?? ()
#27 0x00002049 in ?? ()
iphone
cocoa-touch
unit-testing
asked on Stack Overflow Apr 9, 2011 by Greg • edited Apr 10, 2011 by Greg

2 Answers

8

To allow this to work correctly, you need to go to your testing bundle's build settings and set the Test Host key to $(BUNDLE_LOADER).

In addition, make sure that Bundle Loader key is set to to $(BUILT_PRODUCTS_DIR)/yourAppName.app/yourAppName in the bundle's build settings as well.

answered on Stack Overflow Aug 1, 2011 by memmons
2

Unfortunately, testing on iOS is a hodgepodge with the official tools. There are two types of unit tests. Logic Tests which have no UI invocations and runs in the Simulator. Application Tests which can exercise and manipulate the UI but only runs on the device.

It sounds like you have written Logic Tests that exercise the UI. What you want is to create Application Tests and run that on the device. To do this you have to follow http://developer.apple.com/library/ios/#documentation/Xcode/Conceptual/iphone_development/135-Unit_Testing_Applications/unit_testing_applications.html and create an independent Application Target to run on the device that includes the AppTest target.

But, just an aside is this gets quite tedious as you have to add all code under test and dependencies into each target and application target. You also have to only place logic tests in the logic test target and application tests in the application test target.

answered on Stack Overflow Apr 10, 2011 by Gary Rudolph

User contributions licensed under CC BY-SA 3.0