Obj-C++ Apps and Xcode 2.1 Obj-C Unit Tests: Don’t Forget Step 9!

1. Open Xcode 2.1

2. Make a Cocoa application project. I actually have the OCUnit stuff installed from a previous Xcode version, so my list of new projects included “Cocoa Application + Test”, which I chose (but which you shouldn’t, see below). I called my project “Testy”.

3. Add a C++ class with a member function that’s defined in the .cpp file. I called my class “Testy” as well, and the member function “test()”.

4. In the build settings for the application target, turn off ZeroLink for all configurations: choose “All Configurations” as your configuration in the target’s Info window, select the ZeroLink setting, and hit the delete key. This should turn it from bold to non-bold, and the checkbox to unchecked.

5. Build and run the application, be sure it runs OK, then quit it.

6. Add a Unit Test Bundle target. Add your app target as a direct dependency. Set the target’s Bundle Loader and Test Host settings as specified in Chris Hanson’s wonderful Unit Testing Cocoa Applications post.

7. Add a new Objective-C test case class file. Be sure it has an .mm suffix. In that file, instantiate your C++ class, and call the member function from that instance.

8. Build the Unit Test Bundle target.

It should work, right? You’re using a default project, default targets, following the instructions carefully. But it doesn’t work. The unit test bundle can’t find the C++ symbols from the application.

And the reason why is an additional little wrinkle I discovered today.

9. In your application target’s Info window build settings pane, search on “symbols hidden”. Turn it off. Rebuild your application and your unit test bundle.

Now it works.

Step 9 isn’t needed for applications with Objective-C classes and Objective-C unit test bundles. But it is needed for applications with C++ classes and Objective-C unit test bundles.

So if you have that combination, as I do, don’t forget step 9!

P.S. Second lesson: if you’ve got the old OCUnit stuff on your system, get rid of it before using Xcode 2.1-style unit tests. They don’t go well together. Because I didn’t, I had a lot of “scratch head, fiddle with it some more” sub-steps in the above that you should be spared.