Website Logo. Upload to /source/logo.png ; disable in /source/_includes/logo.html

Hacker School Log

Laura Skelton | Summer 2014 Batch

Hacker School Day 18: Better iOS Testing Tools and Continuous Integration

I continued working on rewriting my Secret Handshake app to be more testable, and writing tests for each method. I moved all of the event management and framework managers out of my view controllers and App Delegate and into their own separate modular implementation files. The delegate callbacks for each of them are now handled by the App Delegate, which manages communication between them upon certain events, such as when the Hacker School API Manager finishes downloading my profile details, the iBeacon Transmitter Handler should start broadcasting my User ID. It’s a much more organized, stable structure, and is much cleaner than it was before, since tasks are much more strictly separated from each other, and the view controllers are handling only things directly related to view management.

I was lucky enough to get some amazing help and advice from Mike Walker about some awesome third-party testing tools for iOS. They are built on top of XCode’s testing functionality, so you still get the advantages of what comes with XCode, with some much more powerful features. It’s this kind of advice that makes me so happy to be at Hacker School. Having a more experienced developer show you the best way to do something and the best tools available for you to use is invaluable, and is an area where self-teaching falls short.

Mike introduced me to Specta, which is a testing framework for iOS that is much more human-readable than using XCode’s built-in testing functionality. It reads like actual specs for the code. You write a series of nested sentences explaining what each piece of code does, and what you expect to happen under different circumstances. Within those statements, you write the actual code test that should validate whether that statement is true in your code.

it(@"sets the user's name when the user loads", ^{
    [_view.user load];
    expect(_view.nameLabel.text).will.equal(@"Ben Day");

With Expecta, you can write your actual test to read like English, which also helps the whole thing to read like a clear outline of your code. This was so exciting to me after working the day before and finding it helped if I wrote in comments above each test what Specta and Expecta include in the tests themselves. If a test fails, it gives useful errors showing you exactly how the code did not meet the specifications.

Instead of something like,

assertThat(@"foo", is(equalTo(@"foo")));
assertThatUnsignedInteger(foo, isNot(equalToUnsignedInteger(1)));
assertThatBool([bar isBar], is(equalToBool(YES)));
assertThatDouble(baz, is(equalToDouble(3.14159)));

you would use Expecta to write something much more readable, like

expect([bar isBar]).to.equal(YES);

I love how it reads so clearly. The human-readable clarity makes it so much faster to spot inconsistencies and errors than when you are devoting more brain power to untangling a less logically-organized series of statements.

Mike also suggested using OCMockito to create mock objects for my projects, which should help with some of the more complicated frameworks I’m using in my iBeacon app.

These testing tools apparently are Objective-C implementations of testing frameworks from the Ruby community. This makes picking up these tools as an Objective-C developer somewhat challenging. The tutorials out there are mainly focused on Ruby developers who are familiar with the frameworks in Ruby, and need to know how to use those same tools in an Objective-C project. The new-to-testing tutorials are much more commonly for Ruby developers. After some searching time, I’ve found some documentation and overviews in Objective-C that I’m going to work through this week, on Unit Testing in Objective-C, using Specta, Expecta, and OCMockito in Objective-C, and Testing in iOS.

In order to use all of these great 3rd party tools, I’m going to have to get over my frustration with CocoaPods and get some practice using that tool to automatically integrate these different tools with my new XCode projects. I don’t like giving up the ability to manually manage these dependencies in XCode (especially when it comes to getting rid of a 3rd party project) and using command-line Ruby tools instead to integrate dependencies, but it’s become clear that the benefits outweight this annoyance.

One of the most exciting new tools I’m going to start using is Travis CI. Travis offers continuous integration for projects hosted on GitHub, and it has supported iOS since April 2013. Continuous integration is great because it automatically checks for problems each time you build or commit your code. If a change you made breaks some other part of the code which, especially in a larger project, you might not have even realized was dependent upon what you were working on, Travis will automatically check and let you know immediately that there’s a problem. This early-warning system can be hugely helpful, because it’s so much easier to fix these kinds of problems the sooner you know about them, before you’ve built more code on top of that initial change. It’s especially important for larger projects, such as some of the open-source projects on GitHub, because it warns you right away when a pull request fails Travis CI’s automatic checks. I’m going to work my way through this tutorial on Travis CI for iOS, as it seems to need a hefty amount of configuration to take full advantage of its potential.

I got a little overwhelmed after all this about just how much I have to learn and how many new tools I need to get comfortable with to become a more awesome iOS developer. The silver lining here is that it’s completely broken through the directionless feeling I had a bit of last week, where I felt like, sure I can come up with some fun iOS projects or learn some new library, but I didn’t feel like I was becoming a much more solid programmer by doing those things.

I decided I’m going to spend as much time over the next month of Hacker School working on a completely from-scratch rewrite of BeerChooser, my first-ever iOS app from back in 2010. It was a decent app considering I started learning Objective-C just that year, and it even was featured in the Lifestyle section of the App Store when it first came out, but I’ve learned SO MUCH since then and it would be amazing to write a useful larger project like this from the ground up using everything I now know about better ways to handle data storage, API integration, and testing.

I’m also planning to rewrite a much cleaner version of the server-side API using Python, as well as a new responsive web app using Javascript to talk to the API and provide the old, bloated website’s functionality to users across multiple platforms. This gives me a chance to get so much practice in with new tools and better practices, as well as a chance to work on some of the other areas I’d like to improve in, like being able to write awesome web apps and work on the API/database integration in a better way. It even lets me work in a bit of Machine Learning, as I’d like to improve the beer recommendations algorithm before I re-launch the app.