Skip to content

Xcode: Debugging Cocoa framework unit tests

So you’ve set up unit testing for your Objective-C Cocoa framework and it’s been working great. But now you’ve written a test and it fails, and you can’t figure out why. It’s time to break out the debugger, but how, exactly, do you do that? Your unit tests are built as a bundle, and you can’t run a bundle.

It’s simple. All you have to do is set up an appropriate Executable in Xcode to run the test rig that runs your bundle, and then debug that. To get started, choose the Project > New Custom Executable menu item. For its name, specify otest — this is the name of the test rig used by OCUnit. Specify /Developer/Tools/otest as the path to your tool.

When you add the custom executable, Xcode will bring up its info window. Switch to the Arguments tab. Here you’ll need to enter some command-line arguments to pass to the test rig and some environment variables to affect how it’s run.

First, add the argument -SenTest Self to your executable. This tells otest to run all of the tests in your bundle. (It’s actually a pair of arguments, but you can add it as one as a convenience.) Then for your second argument specify $(BUILT_PRODUCTS_DIR)/MyTestBundle.octest where MyTestBundle is the name of your test bundle. This tells otest the path of the test bundle to load; $(BUILT_PRODUCTS_DIR) will be expanded to the appropriate build products directory for your project at run time. (If you get the order wrong, just drag the arguments around in the table.)

Troubleshooting note: If this doesn’t work — that is, if otest complains it can’t find your test bundle — change the executable’s working directory (in the General tab) to Built Products Directory and remove $(BUILT_PRODUCTS_DIR) above. Generally this is caused by $(BUILT_PRODUCTS_DIR) not being expanded to a full path, but rather to a partial path relative to your project directory.

Next add a pair of environment variables named DYLD_FRAMEWORK_PATH and DYLD_LIBRARY_PATH to your executable. These will tell the loader to check your build products directory first for frameworks and libraries whenever the executable is run from within Xcode. Specify $(BUILT_PRODUCTS_DIR) for the value of each variable.

Finally, from the Project > Set Active Executable menu choose your new otest executable. This way any time you run or debug within Xcode, it will run otest with the arguments and environment you’ve specified.

To actually debug a failing test, build your tests and set a breakpoint on the line where the failure occurs. Now choose Debug Executable from the Debug menu. Do not choose Build and Debug from the Build menu. You need to use Debug Executable because your build will fail due to the failing test; Debug Executable doesn’t try to build first, it only cares whether an executable is present.

You should successfully stop at your breakpoint!

If your tests take a long time to run — they shouldn’t, they’re unit tests after all, but it can still happen — you may want to just run the tests for one test case, or just one individual test. This is easy too. Rather than specifying -SenTest Self in your arguments to otest, you can specify -SenTest MyTestCaseClassName to run the all the tests in the specified test case. To run just a single test, use -SenTest MyTestCaseClassName/testMethodName instead.

Update July 7, 2007: Added the troubleshooting note about removing $(BUILT_PRODUCTS_DIR) if you get errors about not being able to load the bundle.

{ 5 } Comments

  1. Elise van Looij | February 16, 2010 at 7:01 am | Permalink

    First of all, thank you for this blog post that, though several years old, is still valid. BTW, the warning to not use “Build and Debug” but “Debug Executable” is no longer valid in XCode 3: the latter no longer exists and the former works fine. I have a question for which I can’t find an answer though I’ve posted it on StackOverflow some moons ago: how could one debug a loadable bundle or plug-in? The instructions for debugging a framework seem to apply and the unit tests will run, but the code inside the bundle is not accessible to the unit tests. For instance, I want to test a method in a class that’s not the principal class, but I find that it remains inaccessible to the unit test bundle. I’ve tried setting the bundle loader, the test host and the test rig build properties, but all to no avail: custom classes remain inaccessible and the debugger won’t break on breakpoints inside the plug-in. Any help would be greatly appreciated.

  2. で 素晴らしい物事のスキームあなたはためのB- に関して。 どこあなた混乱する私たちはだった上すべての事実。You know, it is said, the devil is in the details… And it couldn’t be much more true at this point.Having said that, allow me reveal to you just what exactly did give good results.Your writing is certainly rather engaging and that is possibly why I am making an effort in order to comment.I do not really make it a regular habit of doing that.Second, while I can certainly notice a leaps in reason you make, I am not necessarily certain of exactly how you appear to unite the ideas which inturn make the actual final result.For the moment I shall subscribe to your point but trust in the future you actually link your facts better. 銉戙儕銈姐儖銉冦偗 PANASONIC VIERA 銉撱偍銉㏕H-L19C2-K [19V鍨?鍦颁笂銉囥偢銈裤儷/鍦颁笂銈儕銉偘瀵惧繙 銉忋偆銉撱偢銉с兂娑叉櫠銉嗐儸銉?銉併偪銉炽儢銉┿儍銈€€鈥籅S?110搴S銉囥偢銈裤儷銉併儱銉笺儕銉奸潪鎼級]

  3. このブログ負荷に|絵画像で問題うーん誰が ?私は、にしようとしている、その場合には、私の端に問題があるか、それがブログの場合は、。どれ応答はいただければ幸いです。 三菱電機【基本設置料金セット】 6ドア冷蔵庫 「JXシリーズ」(605L) MR-JX61Y-RW ロイヤルウッド (MRJX61Y)

  4. Aja | September 24, 2015 at 8:37 pm | Permalink

    Thank you for making the honest attempt to publish about this.

    It may be extremely useful for me and also my friends.

  5. それはだかどうか|他のみんな の問題を私は知らないがわからないあなたのウェブサイト。 かのような状態になりますこれは、としても表示されますの一部書かれたテキストあなたの内に投稿がオフに実行されている画面。 他人ことができますしてくださいコメント、これは彼らに何が起こっているなら、私に知らせて同様に?私はこれが起こる持っていたので、インターネットブラウザ 前に以前、私と問題問題であること。 それを感謝 [AY-E56DH2-W]銈兗銉夋墪銇凮K锛併偡銉c兗銉?銉兗銉犮偍銈偝銉?銉椼儵銈恒優銈儵銈广偪銉笺偍銈偝銉?楂樻績搴︺儣銉┿偤銉炪偗銉┿偣銈裤兗7000 鍐锋殩鎴匡細18鐣崇▼搴?鍗樼浉200V锝?5A 閮ㄥ眿骞层仐銉兗銉?2015骞淬儮銉囥儷

Post a Comment

Your email is never published nor shared. Required fields are marked *