Category Archives: GHUnit

GHUnit, the 3rd party unit testing framework.

OCUnit Logic Tests Are Dead

… long live OCUnit Application tests.

I’ve been espousing the use of logic tests for quite awhile now. But recently, I’ve had a chance to work with some projects that have a fairly large number of OCUnit application unit tests. To my surprise, these tests run very fast, roughly sub-second per hundreds o tests.

Of course, test execution times will vary depending on the individual project and tests, but it appears that in general, there’s no need to jump through hoops using OCUnit Logic tests, since simply using OCUnit Application tests should work just fine.

This also applies to GHUnit. I’ve seen a project with over 600 tests execute in under 2 seconds.

Anyone have observations that disagree with this?

 

Installing GHUnit on Xcode 4.6

There has been some confusion for awhile about how to get GHUnit running on the latest Xcode version(s). I had thought that these issues were resolved awhile back, but I wasn’t sure. I recently upgraded to Xcode 4.6, and I also needed to add GHUnit to one of my projects, so I thought I’d blog about my experience, see if there are still any issues, and provide some instructions if so. The bottom line is, no. GHUnit works just fine under Xcode 4.6. Read on if you’re curious about the issues I ran into, which were basically just configuration things, nothing broken in GHUnit or Xcode 4.6.

Installing GHUnit

I’m starting with an existing Xcode project, and adding GHUnit. Here’s the steps

  1. Add a new target to your project: use the Empty Application template, no unit tests or Core Data. Name it “GHUnit Tests” or whatever you’d like.
  2. Download a copy of GHUnit from Git. Expand the file if you download as zip.
  3. In your project, right-click Frameworks and select the Examples/MyTestable-iOS/GHUnitIOS.framework directory in the files just downloaded. Set the “Copy items into…” checkbox, and select your GHUnit Tests target (only). Verify that GHUnitIOS.framework has been added to the Frameworks group.
  4. Add -ObjC and -all_load to the Other Linker Flags build setting for the GHUnit Tests target.
  5. Delete the files (AppDelegate.h & .m) from the new GHUnit Tests group (leave Supporting Files subfolder).
  6. In GHUnit Tests/Supporting Files group, edit main.
    1. Replace the last argument to UIApplicationMain (

      NSStringFromClass([AppDelegate class])) with

      with @”GHUnitIOSAppDelegate”

    2. Delete #import “AppDelegate.h”
  7. Select the GHUnit Tests scheme, and run it on the simulator.

So, exactly per the instructions, no problems.

First Problem (Deployment Target setting)

Trying this now on an actual device, I encountered a problem, but not related to GHUnit. I’ve been testing my project on an iPhone 3GS, which is the device I mount on my motorcycle handlebars. By default, Xcode 4.6 sets the Deployment Target to 6.1. Since my good old 3GS is running 5.0, it doesn’t appear in the device list. Instead it just says “iOS Device”. Changing the GHUnit target’s Deployment Target setting to 5.0 fixed this problem.

Second Problem (SenTestingKit)

Now the only thing I had left to do was to add the unit tests to the GHUnit Target. I added one of the OCUnit test case files, and reran. Not surprisingly, I got an error because I hadn’t added SenTestingKit to the GHUnit Tests target. So adding it, and rerunning, I got a similar error regarding OCMock.

Third Problem (OCMock)

The test file I added uses OCMock, so I needed to add the OCMock static library, and then add the path to the OCMock headers to the Headers Search Path build setting.

Fourth Problem (Linker path to SenTestingKit)

And finally, once I had everything compiling ok, the linker had trouble finding the SenTestingKit framework. This was fixed by updating Framework Search Paths:

$(SDKROOT)/Developer/Library/Frameworks
$(DEVELOPER_LIBRARY_DIR)/Frameworks
$(SRCROOT)

Once this was done, the tests appeared and ran successfully.

Now, if only GHUnit supported Kiwi tests…

Back to GHUnit

I was quite embarrassed by all of the Xcode unit testing bugs I encountered during the recording of Unit Testing iOS Applications on Xcode 4 back in February at lynda.com. The default test template crashed, the tests kept passing when they should have failed, sometimes failing when they should have passed, and so forth. The system had been upgraded to Xcode 4.2 days before I got there, and there were numerous severe bugs in the unit test support. Sheesh! I eventually got over my embarrassment and determined that I needed to perform frequent deep-cleans and Xcode restarts as needed, and disable LLDB and used GDB instead. Come on, Apple! Does anybody there test the unit test support in Xcode before releasing it?

At WWDC 2012 I searched for “the unit test guy” to try to find out what they were doing to try to fix this situation. I had hoped to be convinced that Apple was making changes to fix this situation, maybe even unit testing their unit testing framework. The response though was defensive. I was told that the documentation was all wrong, and to go create radar bug reports if I had problems.

After that disappointment though, I had a more encouraging meeting with a developer in the Core Data group. She advocates the use of unit tests, and explained that her group received special treatment by upper management because of the fact that their code includes unit tests. It is therefore very robust and can undergo major changes very quickly and safely.

That’s the good news.

The bad news is that they do not use the unit testing framework in Xcode. They use an old version of SenTestingKit. In fact, I couldn’t find anyone at Apple that uses the unit testing framework in Xcode.

This helps explain how Xcode 4.2 was released with crashes in the default unit tests. Apple clearly does not test their unit test frameworks.

This brings me to conclude that the OCUnit support in Xcode is not important to Apple. It clearly isn’t tested, and I have no evidence that anyone at Apple is actually using it.

So after having spent the past year advocating the use of the new OCUnit support in Xcode 4, I’m reversing my position now and advocating using GHUnit instead.

I like the tight integration of OCUnit into Xcode 4, but I hate having to guess whether a test failure is really a test failure or an OCUnit or Xcode bug.