Category Archives: TDD

Unit testing in Swift

The iOS folks around here are all abuzz about the new Swift language announced by Apple this week. Surprisingly, this information was released publicly, so no NDA required to talk about it.  You can find the information at https://developer.apple.com/swift.

While there are still a lot of questions about the implications of testing in Swift, at first glance it looks pretty straight forward. One nice surprise, reported yesterday on BendyWorks.com, is that  Setup() isn’t needed to create fresh instances of the object-under-test. Simply creating a as a constant stored property of the test case class results in a fresh instance being created for each test.

I’ve run through some TDD katas using Swift, and after some initial adjustment to the new language, I have to say that things appear to work fairly well. I’m really warming up to Swift.

Now the next question is whether or not the existing mock frameworks still work, or how soon we can get updates. No comment from Jon Reid yet, but I’ll bet he will be speaking out soon 🙂

Need-Driven Development

I recently came across a 10 year old article titled “Mock Roles, not Objects“. I recall reading this article at some time in the past, but I guess that I really didn’t get it the first time. This article is awesome, and I recommend reading it. But maybe like me, you need to become fairly familiar with TDD and using mock objects before it will have much impact on your thinking.

When I reread the article, I was immediately struck by the opening 2 sentences:

“Mock Objects is an extension to Test-Driven Development that supports good Object-Oriented design by guiding the discovery of a coherent system of types within a code base. It turns out to be less interesting as a technique for isolating tests from third-party libraries than is widely thought.”

Wow. The article then goes on to explain how the proper use of Need-Driven Development can help in the creation of good, clean architecture. I think that maybe the first time I read this article, I was still stuck in creating relatively few, large objects with lots of methods. After repeated viewings of Uncle Bob’s videos though, I changed my mindset to using lots of small, SRP compliant objects. Without that mindset, it might be possible to misinterpret this article as recommending the use of partial mocks to intercept calls from one method to another within the same object. Been there, done that, got help and am hopefully on the road to recovery now.

I think that there are still parts of this article that I’m not evolved enough yet to fully grok, for example section 4.1. I think I’ll come back and reread the article in another year or so and see if I get it then.

Using “Refactoring” as an Excuse to Skip Writing Tests

I caught myself falling into a bad practice this week. I was starting to use the “Refactor” phase of the TDD loop (Write a test, Write code to pass test, Refactor) to implement new code. In the Who’s Working On What code, at the end of May 27th, commit fb9990…, I had just about everything working with just a single project displayed for each engineer.

So the next thing I wanted to implement was to display more than 1 project for (some) engineers. I’d setup the simple structures to allow 2 to be displayed, knowing that at some point I’d need to make this a variable number using an array of projects.

So I erroneously thought to myself, “let’s just refactor the code to use an array instead of fixed properties. I already have a bazillion tests (about 300), so they should catch any issues.

This might have been an ok approach (but not a great one), except it became hard to tell when I started adding new functionality. Luckily, I had chosen to work off of a branch. When it became apparent that what I was doing was wrong, I simply killed the branch and started over. The problem with that approach is that it allows new code to be written (under the guise of “refactoring”) that might not be actually tested. And one of the chief benefits of TDD is that you can be sure that all the code you write is tested.

So, another lesson learned (or “relearned”?). Only write code that the tests compel you to write.

I Should Have Unit Tested

Ok, it’s confession time. A couple weeks ago I started a working on what I thought would be a very simple app. It’s essentially just a tableview with sort/filter options to keep track of what the 60 or so engineers in the department are working on. It would be stand alone, with the data entered and updated manually. I expected to be the only one using this app, so I chose to just throw it together without unit tests.

What? I know, right? What was I thinking? I was thinking that TDD didn’t make sense for what amounted to a simple prototype. I was thinking that TDD didn’t make sense if it was a personal use app. I think I wasn’t thinking clearly.

So tableviews are fairly simple creatures, with the SDK doing all of the heavy lifting. At the same time though, creating unit tests for it is fairly simple also, since it’s behavior is so well defined. But I needed more than just a tableview. I need a data entry screen to manually enter and edit the 60 engineer records. And that’s where the problems started occurring.

Keyboard dodging is a bit tricky (scrolling an entry field so it isn’t under the keyboard when it appears). I spent a lot of time in trial-and-error getting it working, and it still isn’t working correctly in all situations.

And data needs to be converted and formatting to and from dates and percentages. And that starts to get tricky. Again, I spent a lot of trial-and-error time getting that working.

But then I hit a strange bug, and have spent the past couple days trying to debug it. And then it struck me: the time that I had spent debugging this code could have been used to create unit tests first.

So consider this my formal apology to everyone. I’ve been espousing TDD for a long time, and using this exact situation as one of the compelling reasons. Sorry, I guess I fell of the TDD wagon, but I’m back on now.  I’m restarting this project, and you can be sure that I’ll be using TDD for everything going forward.

First Observations on TDD with VIPER

In a previous post, I mentioned that I was rewriting WhatsMySpeed (now called HowsMyFuel and posted publicly on Github) using TDD and the VIP architecture. I’m committing changes at each step of the TDD cycle. I’m exploring to see if commit comments on Git can be used blog style. Let me know if this works for you.

One of the reasons in VIP of separating the ViewController into 3 components (ViewController+Presenter+Interactor) is to eliminate the Massive View Controller, so common in iOS apps. I’m discovering that one of the up sides to doing this is that I can move many of the unit tests from application to logic tests.

View controller tests typically require running in OCUnit application tests. OCUnit application tests are slower, since the app bundle is loaded. I don’t know how much slower yet, but I hope to test this later, as the number of unit tests gets larger.

So what goes into the View Controller vs the Presenter or Interactor? Normally the View Controller does nearly all the work. That’s why iOS view controllers tend to be huge. And huge typically means hard to read, even harder to unit test. However, I’m attempting to reduce the size and complexity of the view controller by removing all business logic. By that, I mean the logic that decides what an event does.

ViewController should contain basic iOS glue stuff; outlets, actions, etc.

Presenter should contain display-specific business logic, without interacting with the models.

Interactor should implement the business logic, aka use cases. It maps model data to the form needed by the Presenter and/or ViewController.

For example, the HowsMyFuel code as of April 25, 2013 contains code to register a tap gesture recognizer, and handle the tap event to recenter the map display when it is tapped. As is often the case, the event handling code is about 5 times the size of the business logic, which obscures the business logic, or intended behavior. To fix that, I’m going to elevate the business logic into the Presenter, where the expected behavior will be made crystal clear (when map is tapped, recenter the display on the user). Since this behavior is related directly to the UI display, I’ll put it in the Presenter. If it was dealing with Model data and/or not UI display specific, then I’d elevate it even higher to the Interactor.