Exceptions, Unit Testing and Breakpoints, oh my!
Today from my laptop monitor I’m watching Unit Testing with Xcode from iDeveloperTV with Graham Lee and Scotty. On my main monitor I’m working through my ProfitTrain tests, doing some updating and additions.
In ProfitTrain I have unit tests for lots of the models and business math. Some of this math throws exceptions when unexpected values are present. I have a unit test that tests that an exception is thrown when I try to setup some trash value with STAssertThrows().
The problem I now have is that I also like to leave the project running with breakpoints running and that All Exceptions breakpoint set. When I run my tests it hits the breakpoint and pauses the tests. If I turn off breakpoints all test pass fine.
I’m not sure what the right way to handle this is. It kind of bugs me that I have to be mindful of my IDE state before running unit tests. This post is a request for some feedback.
One idea is to turn off breakpoints before running the test, either as general rule for the project or something that is more automated in the scheme (using pre and post shell scripts?). I’m not sure I like this idea as I’m guessing there will be points where I do want to step through test code using the debugger.
A second option is to augment my error code in my app. Perhaps have it look for a macro or flag of some kind and avoid raising the exception? Not sure I like this either.
Feedback very welcome.
Posted on: July 18, 2011 – 1:54 PM

7 Comments
You could install a catch-all top level exception handler and put a breakpoint on that instead of breaking on objcexceptionthrow
objc_exception_throw, that is.How about if you edit the Test section of your Xcode scheme and set the “Debugger” setting to “None”? I think that would mean the tests are run without a debugger attached at all, so no breakpoints would ever get hit. Of course you’d have to turn it back on to do actual debugging of your tests, so that would depend whether that’s more or less of a pain in the butt than disabling the exception when running tests.
@Brian: Yeah that seems to swap one annoyance for another.
@Colin: That might work. I wonder if
STAssertThrowswill swallow the exception. I’ll give it a shot.Thanks for the feedback guys.
Hey, I was thinking about buying iDeveloperTV’s Unit Testing video. How did you like it? My unit testing is woefully inadequate and I’ve been wanting a good practical resource on Unit Testing. Most of the stuff I read are less practical and more conceptual.
@Matt I finished watching the videos last week and enjoyed them a lot. I came into it with a fair amount of testing background so hard to say how good it was for noobs but I did benefit from some of his ideas on how to setup mock objects and more importantly how to build your controllers to work with objects implementing say the NSUserDefaults protocol instead of the singleton itself. “Tell don’t ask!”
I did leave the series with a few more questions:
If you are curious I’d say buy them. If you truly don’t find them useful Scotty has a 100% money back guarantee. Hope this info helps.
Hi Mike, I’m glad you liked the videos. Colin’s suggestion of breaking on the uncaught exception handler’s entry point is a good one: in your unit tests, STAssertThrows() will handle the exception…and besides, you don’t need to set the uncaught exception handler in your test target (especially if you’re using “logic tests”, rather than “application tests”).
If you don’t want to set up a continuous integration system, one thing you can do is rely on Xcode’s build setting to automatically run tests after a successful build. Some people have that on all the time, and others leave it off for debug builds but on for release so they definitely get test results before submitting a build to QA/beta/customers.
Whether you write code with blocks or not is kind of orthogonal to testing it. There are two different situations. If you’re testing a method that takes a block as a parameter (e.g. a completion handler), then you get to pass in your own handler in the tests and use it to find out whether the method does its thing. The other case is when the method internally uses a block e.g. for some API, your test just works as ever: find out whether the postconditions of the method are satisfied. In that second case, the block actually becomes immaterial.
Post a Comment | Comment RSS feed