My team has recently begun using Bob Martin’s Clean Code book and videos to improve our code’s readability. I’ve been completely blown away by how much easier it is to add unit tests to clean code.
I’ve been working through the Xcode project template code to add unit test to it. Trying to add unit tests to the unmodified, template generated boilerplate code is not easy. Some might say impossible or not worthwhile. However, once I started refactoring the code using Uncle Bob’s recommendations, the code magically became easy to unit test.
I highly recommend Clean Code. It will make your life easier.
Classes often have helper methods that are called by the public methods in the class. In order to keep the public interface clean, these helper methods should not be declared in the header file (.h). Instead, these should be declared in a class extension.
A class extension is a category defined on a class without a name. Sometimes these are referred to as anonymous categories. Methods declared in a class extension must be defined in the implementation (.m) file for the class.
In order to access these private methods declared in the class extension, simply move the class extension into a separate .h file, and include it in both the implementation file as well as the unit test file.
Be sure to name the class extension header file something that makes it clear that it should not be used only for testing; for example, include the word “private” or “fortesting”.
There has been a lot of confusion about unit testing view controllers. I’ve had people tell me that one should only unit test model objects and not view controllers. I’ve even been told that it isn’t possible to unit test view controllers. Don’t you believe it.
Let me clarify a few things about unit testing view controllers:
- View controllers typically contain most of the developer written code for an iOS project. Choosing not to test view controllers is essentially making the decision to not test most of the code you write.
- ViewController unit tests should test the methods of the view controller. This means that each test method in the ViewControllerTests.m file should be testing one of the methods of the view controller.
So for example, I would expect there to be a test method named “testViewDidLoad” that tests whether viewDidLoad works as intended. This means verifying that the code you put in viewDidLoad does what you expect the it to do.
- Unit testing a view controller nearly always means writing the view controller methods differently. In untested view controllers, viewDidLoad usually has a LOT of code thrown into it. This works, but is not very testable. Instead, viewDidLoad should call helper methods. Each of the helper methods should do just one thing (Refer to SOLID object oriented principles). Then the unit tests can test those helper methods to verify that the one thing is done correctly. It also means that the test for viewDidLoad probably just verifies that those helper methods are actually called. This can be done using a partial mock object. Each helper method should also be named in a way that makes it clear exactly what that one this is.
- The view controller unit tests should not be testing anything besides the view controller. If the view controller calls another object, then the view controller tests should verify that the other object is called (for example, using mocks), but should not test what the other object does. The unit tests for that other object should test that.
- And as with all unit tests, we should not try to test things that are done by the runtime or iOS libraries.
Unit testing view controllers appears daunting at first, but with a little experimentation and practice, it becomes fairly easy.
Thanks for visiting. This site is all about unit testing your iOS code.
Refer the the About page for some background information about me and why I created this blog. For now, suffice it to say that the state of unit testing on iOS still has a very long way to go. I’m going to try to improve that situation by sharing information about it as I come across it, and as I figure it out myself.
Thank you Conrad Stoll for the great Colorado mountain image that I’m using in the banner at the top of this page. You are an incredible photographer in addition to being one of the best iOS developers that I know.