views:

510

answers:

4

UPDATE: I ended up giving up and added GHUnit to my project instead. I got up and running with GHUnit in a matter of minutes.

UPDATE: You can download the Xcode project here: http://github.com/d11wtq/Cioccolata

I've added a Unit Test target to my Xcode project but it fails to find my framework when it builds, saying:

Test.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.

My framework (the main project target) is designed to be embedded and so has an install path of @executable_path/../Frameworks.

I've marked the framework as a direct dependency of the test target and I've added it to the "Link Binary with Libraries" build phase.

Additionally I've add a first step (after it's built the dependency) of "Copy Files" which simply copies the framework to the unit test bundle's Frameworks directory.

Anyone got any experience on this? I'm not sure what I've missed.

EDIT | I'm pretty sure I'm not supposed to, since a framework is not executable, but I haven't set "Test Host" and "Bundle Loader". This should (to my understanding) all be ok since the test bundle is linked against the framework and will load it just like any other bundle.

EDIT | I think I'm nearly there. I read the following article which dictates the use of @rpath instead of @executable_path.

http://www.dribin.org/dave/blog/archives/2009/11/15/rpath/

In this case it makes perfect sense since the OCUnit test bundle is NOT an executable, it's a plain old bundle, so @executable_path is not compatible. So now my framework has its installation directory set to @rpath and the Test target has its runtime search paths (rpath) defined as the build directory. This saves me having to copy the framework into the test bundle and means that overall the resulting framework is much more flexible in nature since it can live anywhere.

Now, I also realize that I should have set the Bundle Loader on the Test target, so this is now set to the path of the framework binary.

I can build the test target and I can #import classes from the framework, error free. But as soon as I try to instantiate a class from the framework I get the following error:

/Developer/Tools/RunPlatformUnitTests.include:412: note: Started tests for architectures 'i386' /Developer/Tools/RunPlatformUnitTests.include:419: note: Running tests for architecture 'i386' (GC OFF) objc[50676]: GC: forcing GC OFF because OBJC_DISABLE_GC is set Test Suite '/Users/chris/Projects/Mac/Cioccolata/build/Debug/Test.octest(Tests)' started at 2010-05-21 12:53:00 +1000 Test Suite 'CTRequestTest' started at 2010-05-21 12:53:00 +1000 Test Case '-[CTRequestTest testNothing]' started. /Developer/Tools/RunPlatformUnitTests.include: line 415: 50676 Bus error "${THIN_TEST_RIG}" "${OTHER_TEST_FLAGS}" "${TEST_BUNDLE_PATH}" /Developer/Tools/RunPlatformUnitTests.include:451: error: Test rig '/Developer/Tools/otest' exited abnormally with code 138 (it may have crashed). Command /bin/sh failed with exit code 1

My test method does nothing more than allocate and subsequently release a HelloWorld class I created to help debug this setup:

- (void)testNothing {
    CTHelloWorld *h = [[CTHelloWorld alloc] init];
    [h release];
}

If I replace these lines of code with an STAssertTrue(YES, @"Testing nothing"); the error goes away, even though the class is still being imported.

A: 

You might have some luck with the following article, in particular adding DYLD_FRAMEWORK_PATH and DYLD_LIBRARY_PATH to your executable might help.

Alex Winston
Hi, thanks for the link. I tried adding these settings to the build config for the test target but I still get the same problem. Hmmm.
d11wtq
+1  A: 

Since nobody else has chimed into this question, I'll finish off by saying SenTestingKit really unimpressed me with the complexity (and ugliness) of the setup for my needs. I highly recommend GHUnit which runs in a UI (or on command line if you prefer) and supports using gdb out of the box. It took me a matter of minutes to download and use GHUnit in my project.

It's pretty too. Apple should ship it with Xcode instead of SenTestingKit IMHO.

d11wtq
Coming from the Visual Studio + ReSharper world, GHUnit is just what the doctor ordered. We've got to talk this up... it seems cruel to go on letting TDD practitioners go on with the SenTesting stuff the way it's packaged up with Xcode right now.
Hugh
A: 

It happened to me a few times. I know you switched to GHUnit, but just in case someone is interested: after going around this for a LONG time I realised that Xcode just didn't add the code classes (.m files) in the Compile part of the target, but in the Copy Resources part of the target. Moving it to the right place solved the issue.

Aviad Ben Dov
A: 

Ok, so I too fought with this, and here is what I have found to be the simple solution to the problem:

  1. Create your application/framework
  2. Create your test bundle "additional target", do not set a dependency on your main
  3. Drag the files you want to test from your classes to the "compile sources" of your test bundle target
  4. Create your test cases, adding them only to the test bundle target
  5. compile test target, tests run.

Note, this means you simply have to compile your test bundle target when you want to run your tests. Ideal, no; works, yes.

Apple really automate this and get it working correctly, out of the box.

Dave Raymer