Authentication rules in a handcrafted iOS application with TDD

This is the first part of a series of posts about making an iOS Application appreciating every step of Software Development process. During the process we are going to focus on the building process much like an artisan would do, so forget about crazy deadlines and there effects in our code. Coding supposed to be fun, let’s bring back enjoyment to the table.

Main topics will be about TDD, views constructed by code, Clean Architecture, SOLID principles and integration with some Backend As a Service (BASS). Each post will track completed issues at GitHub of the project.

This App will have chat groups generated automatically by a combination of users birthdates. Users would be able to chat with other people with similar stats like:

  • Birthday
  • Birthdate
  • Zodiac sign
  • Among other combinations

Getting started

My intent with this project is to not use Storyboards or Xibs. For that, the Xcode project consist in a single view application template plus some cleaning tasks.

Create a single view application and check the “Include Unit Tests” option
Clean main interface option, remove Main.storyboard and remove ViewController.swift
I also delete the created default test file. And now we are ready!

Let’s start with the authentication process, but not all of it, for now we are only interested in the registration part. This part has some validations and important behaviors. This implementation will allow us to interact with some BASS stuff, which represents an important piece of the apps puzzle. In this post we will cover:

  • Test Driven Development
  • Input data validation
  • Prepare some integration with an external service
  • You can check the related github issue here.

The user registration use case

The project will be developed using a bottom-up process. So, instead of making a sign-up or a sign-in screen, we will start by writing tests and rules. The first test is about to try to register an user with empty email value.

Creating the first test file

The above ugly and stupid test is the starting point. At this point, Xcode is complainin about the missing RegisterUseCase class, missing register function, and missing shownInvalidEmailErrorMessage property. So lets do what the test is asking for.

Yes, it sounds weird. The above code is far from what the system needs for the final use case of registering an user. But this code is the minimum necessary to make the test pass. Throughout this project you will see this TDD mindset.

This guy knows about the importance of the test. Be this guy 🐶

After green tests, it is time to refactor the use case class. The first weird thing is the mutating keyword at the register function. This keyword is needed because the function is trying to change a struct value which is immutable by default.

This App will use an architecture called Clean Architecture which divide the software in layers. These layers are essentials to isolate components and responsibilities separated by behavior. The Clean Architecture and SOLID principles deserve a separated post that I will talk soon.

By separating the software into layers, and conforming to The Dependency Rule, you will create a system that is intrinsically testable, with all the benefits that implies.
Martin, Robert. “The Clean Architecture” 2012
The layers in Clean Architecture

Also, this use case is saving a state that should be in the presentation layer. Not in Application Business Rules layer. To solve this issues we could create a presenter.

… We also do not expect this layer to be affected by changes to externalities such as the database, the UI, or any of the common frameworks. This layer is isolated from such concerns.
Martin, Robert. “The Clean Architecture” 2012

The protocol above will be the presenter. And its implementation does not matter for the use case. The use case just needs something that has the failure method. In our test environment we will be using a Test Double representation of the presenter which will be of the stub double type.

For testing purposes, we can replace the real DOC (not the SUT!) with our equivalent of the “stunt double”: the Test Double.
Meszaros, Gerard. “Test Double” 2009
Stubs provide canned answers to calls made during the test, usually not responding at all to anything outside what’s programmed in for the test. Stubs may also record information about calls, such as an email gateway stub that remembers the messages it ‘sent’, or maybe only how many messages it ‘sent’.
Fowler, Martin. “Mocks Aren’t Stubs” 2007
Use case changed to use the presenter through dependency.

The presenter will be used as a dependency to the use case, doing so would conform with SOLID principles, more specific the Dependency Inversion one . The principle states:

A. High-level modules should not depend on low-level modules. Both should depend on abstractions.
B. Abstractions should not depend on details. Details should depend on abstractions.
Martin, Robert. “The Dependency Inversion Principle” 2003

That said, now the tests are failing again. Do not make an ugly face for this, it’s a good sign. Xcode complaining is part of the game, enjoy it =). After doing what the tests asked for, the code should look like:

Now it is possible to run the tests, and see the green lights! The next step consists in to making new tests see them fail and so on. Following the same mindset as before, we will create a new test for empty name error handling.

Again, Xcode is showing an error for the shownEmptyNameErrorMessage property. After adding this variable to the presenter it will be possible to run the tests. However it keeps failing. That happens because the error behavior for empty email stills unchanged. So it is necessary to go back to the use case and make appropriate changes to solve this issue.

Now Xcode is showing errors about the not existing failureEmptyName and faiulreEmptyEmail methods. After try running the tests with these compile errors, it is necessary to create the expected methods.

All error handling scenarios follow the same as above. Repeat all these steps for every remaining scenario would make this post huge, so It is absolutely mandatory to clone the repository in order to check all the different cases. Next we need to address another important part responsible for delivering input data to the adjacent layer. This layer will be replaced in the future for a BASS integration and without it would be impossible to persist data in the Cloud Service for instance.

The software in this layer is a set of adapters that convert data from the format most convenient for the use cases and entities, to the format most convenient for some external agency such as the Database or the Web. It is this layer, for example, that will wholly contain the MVC architecture of a GUI. The Presenters, Views, and Controllers all belong in here
Martin, Robert. “The Clean Architecture” 2012

Authentication gateway

To say “Hi!” to an external world, we will adopt the same approach as the presenter, but this time using a guy called Gateway, which is also injected in the use case. You can check the complete test case below.

You can see the same TDD mindset in the remaing cases as well as all Test Doubles implementations here.

User entity

User entity will be an object used trough layers. For this purpose, it is essential that user has a name and birthdate besides email and identifier.

An entity can be an object with methods, or it can be a set of data structures and functions… these entities are the business objects of the application. They encapsulate the most general and high-level rules.
Martin, Robert. “The Clean Architecture” 2012

The next post will address the implementation details of a real Gateway using a cloud service as well as it's respective tests. Don’t forget to follow the project on it's Github page ⭐️.

Ps: If you like this post, share it on twitter, recommend it on medium, or both =). This really helps me to reach more people. Thanks a lot ..


Martin, Robert. “The Clean Architecture” 2012

Meszaros, Gerard. “Test Double” 2009

Fowler, Martin. “Mocks Aren’t Stubs” 2007

Martin, Robert. “The Dependency Inversion Principle” 2003

Nunes, Ronan Rodrigo. VIPER — Arquitetura limpa em nossos APPs