OCUnit testing an embedded framework
Asked Answered
B

6

5

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.

Bacchic answered 19/5, 2010 at 16:1 Comment(6)
Any way you could gut your project and post it online? I would be more than willing to take a quick look. I struggled with a similar problem some time back but can't remember exactly what I did. Looking at a broken project might help rattle my brain.Carpio
I'm putting it up on github now... will post in a tick.Bacchic
Not really much in the way of secret code here. It's barely even started ;) github.com/d11wtq/CioccolataBacchic
I've given up. I download GHUnit and got up and running in about 10 minutes. Same test case, different test runner. Make more pleasant to work with too.Bacchic
Please add a "GHUnit" tag to this question.Oahu
Better late than never; I've tagged it.Persis
B
4

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.

Bacchic answered 23/5, 2010 at 22:49 Comment(1)
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.Oahu
D
3

I had the same problem but with Kiwi Unit Testing framework. My problem was that "Test Host" was not set under Build Settings. When I set it to $(BUNDLE_LOADER) everything worked perfectly. Verified using Xcode 4.5.2 iOS SDK 6.0.

Deluxe answered 15/11, 2012 at 7:42 Comment(0)
S
2

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.

Somersomers answered 25/9, 2010 at 11:22 Comment(0)
C
1

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

Carpio answered 19/5, 2010 at 16:34 Comment(1)
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.Bacchic
R
1

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.

Ruthven answered 23/10, 2010 at 13:17 Comment(0)
P
0

I do agree with the recommendations for GHUnit, it totally rocks!

However, I've switched to using OCTest after Apple integrated it in xCode4 so I'm trudging through the issues.

The linking problem reported here occurred for me after we added new files to the project. These included ViewControllers and xibs but the files were marked in xcode for both the application and the test target. I discovered the files by inspecting the OCTest bundle in the derived data directory. ~/Library/Developer/Xcode/DerivedData/ Right click and choose "Show Package Contents" from finder. Look for stuff that does not belong there, ie: application classes and resources. Removing these files from the "Compile Sources" or "Copy Bundle Resources" corrected the linking error.

Perspicacity answered 18/7, 2011 at 4:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.