GH-Unit for unit testing Objective-C code, why am I getting linking errors?
Asked Answered
P

3

5

I'm trying to dive into the quite frankly terrible world of unit testing using Xcode (such a convoluted process it seems.)

Basically I have this test class, attempting to test my Show.h class

#import <GHUnit/GHUnit.h>
#import "Show.h"
@interface ShowTest : GHTestCase { }
@end

@implementation ShowTest
- (void)testShowCreate
{
    Show *s = [[Show alloc] init];
    GHAssertNotNil(s,@"Was nil.");      
}

@end

However when I try to build and run my tests it moans with this error: -

Undefined symbols:

"_OBJC_CLASS_$_Show", referenced from:

 __objc_classrefs__DATA@0 in ShowTest.o

ld: symbol(s) not found

collect2: ld returned 1 exit status

Now I'm presuming this is a linking error. I tried following every step in the instructions located here: -

http://github.com/gabriel/gh-unit/blob/master/README.md

And step 2 of these instructions confused me: -

In the Target 'Tests' Info window, General tab:

Add a linked library, under Mac OS X 10.5 SDK section, select GHUnit.framework

Add a linked library, select your project.

Add a direct dependency, and select your project. (This will cause your application or framework to build before the test target.)

How am I supposed to add my project to the linked library list when all it accepts it .dylib, .framework and .o files?

Pain answered 9/4, 2010 at 20:25 Comment(0)
C
7

If the target you are testing is an application, you'll need to manually include the Show.h/m files in both your main target and your test target.

I also updated the README to reflect this:

  • If your main target is a library: Add a linked library, and select your main target; This is so you can link your test target against your main target, and then you don't have to manually include source files in both targets.
  • If your main target is an application, you will need to include these source files in the Test project manually.

Sorry for the confusion! Having to include files in both targets is not ideal.

Curtilage answered 9/4, 2010 at 23:30 Comment(2)
Excellent thanks for the quick reply Gabe (and the clarification in the README file!) it appears to be working now.Pain
Gabe, isn’t there any other way? for example something like this #6461574, adding sources to both targets is a little messy and we have to keep that in mind every time we add a new source file, I am not complaining, just curious :)Kinny
R
0

You have to have an @implementation for Show.

Or you could use

Show* s = [[objc_getClass("Show") alloc] init];
...

or

Show* s = [[NSClassFromString(@"Show") alloc] init];
...

to resolving the class in run-time.

Romy answered 9/4, 2010 at 20:29 Comment(4)
Thanks for your answer. Is this really the way things should be done though? I can't help but feel this is a workaround rather than an actual fix.Pain
....also it's worth noting that Show is a class in my project I am trying to test against. The testing stuff is in a separate target with a direct dependency to my projectPain
@djh: the linker clearly cannot find the Show class. Make sure you've included the Show.m file in your testing target.Romy
Thanks KennyTM, this is what I've done and it's working now :' }Pain
X
0

Somehow Apple's example works without duplicating the .m files in the target.

Download Apple's unit testing sample code (iPhoneUnitTests.zip) here:

http://developer.apple.com/IPhone/library/samplecode/iPhoneUnitTests/Introduction/Intro.html

Click on the CalcTests target. Only CalcTests.m is in this target.

Build the target. It builds without any link errors for CalcAppDelegate or other classes.

What's the magic that makes this work?

Xerography answered 10/4, 2010 at 2:52 Comment(2)
Here's why Apple's iPhoneUnitTests example links... They are careful to avoid things like: Calculator *calculator = [[Calculator alloc] init]. Instead, they only do things like: CalcAppDelegate *delegate = [[UIApplication sharedApplication] delegate]; It's unfortunate to be restricted this way, and if you need to work around it, you have to do what KennyTM suggests.Xerography
Maybe I'm getting confused about what unit testing actually is in an objective-c context? At work I use JUnit for Java development so have pretty good experience with TDD and unit testing where classes need to be directly tested. Thanks for the reply anyway :' }Pain

© 2022 - 2024 — McMap. All rights reserved.