After a short introduction in my first iOS testing article I will describe how I set up basic unit testing on iOS.
Complication No. 1, “the Apple way”: XCode comes with a unit test framwork, OCUnit, but unfortunately its integration is a little bit strange. You create an octest bundle that’s “somehow” (I didn’t try to understand how this is working in detail) loaded into your normal project target and then will run your unit tests.
Usually I would simply create a second binary that contains the test sources and the production sources and links to the same libraries plus the libraries needed for testing.
The only advantage I see in using the bundle approach is that I do not have to create a test target with nearly the same setup for the unit tests (copying all settings, adding all classes you want to test and so on…).
One annoying drawback is setting it up for debugging. Sometimes it is useful to step trough a test to understand where it is going wrong but you will need additional setup to debug your unit tests with breakpoints. That’s inconvenient but possible without to much work for normal MacOSX development (i.e not iOS). For iOS this is getting more complicated. As the article says: “What a mess”.
Another drawback is that you can’t run the tests in the simulator or on the device itself because your test bundle is not an ordinary iOS app.
Solution to Complication No. 1: While looking for iPhone/iOS test resources I found Google Toolbox for Mac (GTM). First I was wondering why I would need it but after being a little bit ;-) frustrated by the setup of the standard Apple way above, I gave it a try.
Basically you create a normal standalone iOS app as part of your project. You just have to add a couple of GTM source files to your test target app (a copy of the production app), setup a “run script” build phase (to run the test after they are built) and you are done. This is described in the GTM iPhoneUnitTesting instructions.
Note: I had to remove the MainWindow.xib from the plist file created for my test target. With the xib set I got some complains about the app being unable to load it.
CI Tip: I copied the required files of GTM to my subversion project so I do not have to link to external files when I’m going to setup the Jenkins/Hudson build. 2011/2: See also iOS: Setting Up Advanced Unit Testing Take Two.
The only difference for creating new tests is that you have to use GTMTestCase as base class instead of SenTestCase. But that is not a big issue and GTMTestCase itself is based on SenTestCase. Which is nice because it will automatically play well with OCMock and OCHamcrest (which will be covered in the next article).
A lot simpler than the default way. Nice is that you will not need any extra setup to step into your test code. Just set breakpoints and run the test target. And because it is an ordinary app it will run in the simulator and on the device.
GTM has more stuff to explore (e.g. support for UI testing, additional asserts) but I have not yet played with it.
Summary: with GTM I can easily debug my test cases and run the test in the simulator and on the device. Not bad!
Advice: go with Google Toolbox for Mac for unit testing on iOS.
In iOS: Setting Up Advanced Unit Testing I will pimp the unit testing environment with OCMock and OCHamcrest which has a few new complications.
This is the 2nd article of iOS: Setting Up a Test Environment is a Mess.