Step by Step Walkthrough of iOS Test Driven Development in Swift

The following is an excerpt from my book Effective Unit Testing. It walks you through the TDD process in great details.


Test Driven Development, or TDD, means you write a failing test first, and add as little code as possible to make it pass. As you go, there can be multiple steps you need to take before a test eventually passes. When all your assertions are verified, your feature is complete. Therefore, when all tests pass, your app code will already be covered by unit tests. You don’t need to spend extra time to add tests afterward. There are a lot of resources about the process of TDD on the Internet, so I’m not going to elaborate it here.

The Red-Green-Refactor TDD Cycle

In essence, TDD is performed with the Red-Green-Refactor cycle. The three steps are:

  1. RED – Write a failing test
  2. GREEN – Write the minimum amount of code to make the test pass
  3. REFACTOR – Refactor both the app code and test code

You write a failing test to go into the RED state. Next, you write just enough code to transition to the GREEN state. Finally, you REFACTOR both your app code and test code while staying in GREEN. You then move on to the next test.

The Ordered Steps of TDD

Some people think they should write the assertions to fail first. But I have a different take on this. At the beginning, you don’t even know what the function signature looks like. You just draw a blank. It’s hard to write an assertion. What is the name of the function, its arguments (if any), the return value (if any)? Is it synchronous or asynchronous? Does it return results in a delegate method? Any optionals or nil’s we need to account for? Will it generate errors?

Continue reading →

How do you mock a singleton class

This is a question that came up in my mentorship program Slack team. I think it’s worth a blog post.

I’m trying to set up some tests according to the templates and the new book. I’m struggling with one small detail. In the book, you set up an ordersWorkerSpy, which is derived from a normal class. My question is: What to do if that class is a singleton, which is accessed through something like ordersWorkerSpy.shared?

Let’s work through a code example.

Continue reading →

Synchronous Operations

Do you know the original iPhone was released a little more than 10 years ago? Back in the days, apps were simple. Remember a fart app could generate millions of downloads and dollars?

Fast forward to today. Modern iOS apps are so much more complex than those back in 2008.

The networking, persistence, and performance requirements all push your apps to perform more and more asynchronous operations. The Clean Swift architecture is ideal for that with its unidirectional flow of control in the VIP cycle.

So much about asynchronous operations. What about synchronous operations? There is still a need for synchronous operations in your apps.

In this post, I’m turning back the clock. I’ll talk about the various approaches the Clean Swift architecture can take to handle synchronous operations.

The code for the sample project used to explore synchronous operations in this article can be found on GitHub.

Continue reading →

Pass data backward more elegantly without using delegation

If your iOS app consists of more than one screen, you’ll almost certainly have to pass data from one screen to another. MVC or not, this is easy to do when you present a new view controller. You simply set a property in your view controller or some other class associated with the destination.

But what about when you dismiss a view controller? And you want to pass data backward to the previous view controller?

In this article, we’ll look at two solutions to pass data backward:

  1. Delegation
  2. Data store

Continue reading →

How to test your viewDidLoad() method

Even if you’ve been an iOS developer for one single day, you must’ve come across the situation where you need to do something when the viewDidLoad() method is called. Okay, easier enough. Just put some code in there.

But how do you test it? How can you ensure the viewDidLoad() method is called – your view is fully loaded – before your view controller tests execute?

This is very important. If viewDidLoad() is not called before your unit tests run, all tests fail. Nothing happens. You may also find that your tests sometimes pass, sometimes fail. And you have no idea why. This is likely a timing issue. The viewDidLoad() is called, but before some of your tests execute, and after some of your tests execute.

Read on to find out how to reliably test your view controller and its viewDidLoad() method.

Continue reading →