Testing Business Logic in Interactor

When it comes to writing tests for your app, how do you know which methods you need to test? I answered this question in my last post. Today, you’ll learn how to write tests for the CreateOrderInteractor class – the interactor that contains our CleanStore app’s business logic.

Let’s dive right in.

Create the XCTestCase for the interactor

In Xcode, choose File -> New -> File, then select Test Case Class. Enter CreateOrderInteractorTests for class. Make sure the CleanStoreTests target is checked. Click Create. The CreateOrderInteractorTests.swift file is created.

In the last post, you already learned that you need to test the boundary methods. Here are the CreateOrderInteractor’s input and output protocols again:

The nice thing about Clean Swift is it tells you exactly what methods you need to test at the top of the file. For CreateOrderInteractor, you need to write tests for both the shippingMethods variable and formatExpirationDate() method. You may ask – how do you test a variable? The shippingMethods variable is just a getter method, so it is no different, as you’ll soon see.

Continue reading →

Is it necessary to test every single method in your code?

When TDD started to gain popularity, it felt like a virus, a contagious one. Suddenly every developer started to write tests for their code. But just like a virus outbreak, nobody really knows exactly what to do? Do I have to write tests for every single method in my app?

  • Do I need to test this network call? What if the API goes down? My tests will fail!
  • What about this init call? It is just assigning initial values to some variables. Isn’t that too trivial to test?
  • This method is 138 lines long, doing 5 different things, with 12 possible edge cases. Do I write 12 tests for this one method? Or just one test case to cover them all?
  • I just changed this one line and 34 tests broke. Now I just added 34 things to my todo list. My tests are fragile!

Thanks TDD, but no.

Does this sound familiar to you?

I found myself spending more time to fix my broken tests than writing code that do meaningful work. I couldn’t really see the value TDD was supposed to provide. I even felt like I was fabricating the tests just to make them pass. I eventually lost confidence in them. And my interest in TDD waned.

But TDD does seem like a good thing

Does it have to be this way? Why do all the great programmers like Uncle Bob and Martin Fowler swear by TDD? They certainly found its benefits. They wouldn’t have done it otherwise. Are they just born inhumanly tolerant of broken tests?

Over time, I learned that I didn’t have to play slave to my tests. I learned to be master of them. And to answer the original question. No, you do not have to write tests for every method.

You only have to write tests for the boundary methods. That’s one of the biggest takeaway I got from watching all of Uncle Bob’s talks on Clean Architecture I could find.

I have applied these same techniques to iOS apps. As a result, I find testing much more enjoyable. Most importantly, I now have confidence in my tests to tell me when I break something. Tests become simpler to write too.

Continue reading →

The Swifty Little Mocker

In my last post, I wanted to focus on showing you how Clean Swift works. So I didn’t write any test. You saw how Clean Swift can help you organize your codebase, help you write clean code, and find things later. You learned how to extract your business logic into the interactor and presentation logic into the presenter in the VIP cycle. Finally, you saw how Swift protocols help you decouple your objects.

This post focuses on these protocols that result in a side (or rather main) benefit: Much easier unit testing. Without tests, we can’t be confident the changes we make do not affect existing code.

But first thing first.

Based on Uncle Bob’s The Little Mocker, the following is a short introduction to the different kinds of test objects – in Swift. I highly recommend you read his funny yet educational post.

Java interface == Swift protocol

Nuff said.

Test double

The name test double refers to the whole family of objects that are used in tests.

Dummy

You pass a dummy as an argument to a function when you don’t care how it’s used. As part of a test, when you must pass an argument, but you know the argument will never be used in the method being tested, you pass a dummy. Since a dummy is never used, it can return anything or nothing. Returning nil is perfectly acceptable and most logical.

DummyAuthorizer is a test dummy and returns nil because we don’t really care.

Continue reading →

Clean Swift iOS Architecture for Fixing Massive View Controller

The Clean Swift Handbook is an updated version of this blog post, plus additional chapters to cover the entire CleanStore sample app. It also works with the latest versions of the Clean Swift templates, Xcode, and Swift. Check out the handbook for even more bonus materials.

Your client asks for an estimate to fix a bug. You tell him maybe a couple hours. But you know deep down in your gut that you just aren’t sure. You just have to give a number.

If it takes longer than your guesstimate, it comes back to bite you. “I thought you said it would be done in a couple hours.”

Promise broken. Trust lost. Resentment developed. Client fired. Money lost.

To make matters worse, as developers, we have a tendency to underestimate how long something will take.

Maybe the problem lies in the client? They just don’t understand how development works.

  • They don’t know how complicated that thing is.
  • They need to stop changing requirements.
  • They should focus on functions, not UI first.
  • If only they had asked me to do that 2 months ago while the code was still fresh, it would have taken less time.
  • Add your own favorite lines here

You have to understand the code. Navigate through 50 classes, protocols, and methods. Trace through various conditionals and loops. Identify the relevant line. Reproduce the bug. Make a change to see how it behaves differently. Rinse and repeat until you fix the bug.

While doing all of these, you fear you may break something else. Because there is no unit tests to prevent regression.

This same vicious cycle happens every time you need to fix a bug or add a new feature. Thanks to Massive View Controller.

Continue reading →