Saving time with Sourcery
Some context before we begin.
At eDreams ODIGEO, the iOS team is fully committed to testing and making the clean architecture of our iOS apps.
We use VIPER architecture because it perfectly fits our needs. We are quite a big team, and with this architecture we are able to reach a homogeneous codebase, being able to have two people working at the same time on the same module and to avoid code conflicts. We meet the SOLID principles, helping testability and reaching a high code coverage.
One of the VIPER implementation inconveniences is that we need to generate several files for each module: Views, Interactors, Presenters, Routers, DataManagers… This means that when testing, we need to write mocks for every component mentioned. It becomes a boring and recurring task, not to mention that we need to change the mocks every time we change their corresponding items. That’s when Sourcery steps onto the stage.
Sourcery to the rescue!
Before we begin: What is Sourcery? According to its GitHub description: “Sourcery is a code generator for Swift language, built on top of Apple’s own SourceKit. It extends the language abstractions to allow you to generate boilerplate code automatically.” The key point here is that it generates repeating code by itself. Let’s see how it helped our team and it will be crystal clear.
I am not going to go into details about Sourcery installation and usage. You can find all the related information on the repository: https://github.com/krzysztofzablocki/Sourcery made by Krzysztof Zabłocki
In this example, we will see how to test a VIPER module without Sourcery-generated code, and then compare it to an example with it. We have a very simple VIPER module, where we have a View, a Presenter, and a Router that implement the following protocols:
Now, this is what our presenter would look like:
We can see that our Presenter has two dependencies: Router and View. So we need to create a mock for both of them. Luckily, VIPER encourages dependency injection, so we simply need to create classes that implement each of these protocols. A possible implementation would be the following one:
Once we have created the mocks, let’s see how our test class would look:
This time, writing the test and both mocks has been as easy as pie. But what if router and view had more methods? Or what if we add an interactor? I will tell you: we would be spending lots of time writing mocks instead of tests, and tests are what really matter here.
Stop writing mocks!
One of the Sourcery templates is AutoMockable. It is a template that saves us lots of time when it comes to writing mocks for our VIPER modules.
So what we do next, is we add AutoMockable template to our project, and we create an empty protocol named AutoMockable.
And then, making all the protocols we want to make mock objects of, inherit from it.
So in our example, it would look like this:
And the generated code would look like this:
It looks pretty similar to what we have written, and it saves us a lot of time! 🎉
Our example was very simple, but if we had functions receiving parameters, the generated mock would store those parameters too.
We find many positive aspects of using AutoMockable. In our case, is that it forces us to fulfill part of SOLID principles (Liskov substitution principle, Interface segregation principle, and Dependency inversion principle), although VIPER was already doing it. And the most important part is that we do not spend time manually writing mocks anymore (a recurring and boring task), so it allows us to only think about tests.
And last but not least, AutoMockable is not the only Sourcery template. It has lots of them, and if it still does not fit your needs, you can even create your own 😉