Becoming a better programmer: Test-Driven Development
As I’m enjoying programming again (and more so every week), I started to think consciously again about improving myself as a programmer. After a recommendation of breun I started reading Clean Code, which I can definitely recommend.
One of the things I have always felt bad about professionally is not doing Test-Driven Development. Back when I was programming Haskell a lot I did do a lot of type-driven development, which overlaps a bit: you write down your types and then try to implement it. However, in Objective-C the type system isn’t of much use (compared to Haskell), so I really had to do it: write tests.
Another really big motivation is that I took over a project from another developer. The project was huge, and there were no tests at all. I ended up breaking things multiple times without realizing it (and I only found out after deploying it to the testers). I pledged to myself to do better than that.
Before I set off to write some tests, I had to find a testing framework. There is a great community wiki on StackOverflow called iOS Tests/Specs TDD/BDD and Integration & Acceptance Testing, but it’s also a bit overwhelming.
I started out by using the built-in Unit Testing framework that’s provided by Apple (see: XCode Unit Testing Guide). However, writing unit tests is quite hard for GUI code. As I wanted to test a new UIView subclass that I was developing, I had to test things such as tapping and inspecting other views.
Then I stumbled upon KIF (again, after a recommendation from breun), an open source integration testing framework by Square. As advertised, it was easy to configure and set up, and I was writing tests very soon after that. For example, here’s a scenario that tests whether my view closes, and even when you haven’t used KIF before you can understand exactly what it does:
KIFTestScenario *scenario = [KIFTestScenario scenarioWithDescription:@"Test that the picker closes when tapped outside"];
[scenario addStep:[KIFTestStep stepToReset]];
[scenario addStep:[KIFTestStep stepToAppear]];
[scenario addStep:[KIFTestStep stepToWaitForViewWithAccessibilityLabel:pickerAccessibilityLabel]];
[scenario addStep:[KIFTestStep stepToTapViewWithAccessibilityLabel:@"Tap to close"]];
[scenario addStep:[KIFTestStep stepToWaitForAbsenceOfViewWithAccessibilityLabel:pickerAccessibilityLabel]];
So far, I’m quite happy with the combination of KIF and the built-in unit testing. I’ll try to apply it to more of my projects, and probably be a better programmer because of that. At least when other people will read my code they can use the tests as documentation to see what the code should do.