When we take the Test Driven Development(TDD) approach to write code we eventually ask ourselves a couple of questions: Have I covered all possible use cases? Have I written enough unit tests?
What helps me is writing a bulleted list of functional requirements for the feature I am developing. Having a clear list of things the feature I am working on needs to do, helps me decide what exactly I need to test with unit tests and which unit test to write first. I will demonstrate how I do this with a very simple example in this blog post.
Let’s assume I need to create a User Registration Form Model structure and develop code that helps validate if the provided user details are acceptable and can be used to create a new user account.
Step 1. Define What Needs to be Developed
My first step will be to define what exactly I need to develop. In this case, I need to create a model structure for the User Registration Form. So I need to define a list of fields the form will have.
I will create a new document or write in my notebook the following:
Form structure
- First name,
- Last name,
- Email(which is going to be a user name),
- Password,
- Repeat password
Define Required Fields
In this case, all fields are required.
Define Validation Rules
Before user details can be sent to a backend web service I need to validate the user-provided information to make sure all the required details are provided and valid.
Validate that:
- The First name is not empty, is longer than 1 character, is shorter than 15 characters,
- The Last name is not empty, is longer than 1 character, is shorter than 15 characters,
- The user email address is not empty. The email address contains ‘@’ character and contains at least one ‘.’ dot. The email address is longer than 9 characters.
Email validation rules are much more complex than these ones but for the sake of simplicity, I will use only these ones, - The user password is not empty and is longer than 8 characters,
- The user repeat password matches the first password.
Now, when I have a bulleted list of things I need to develop, I can think of a number of unit tests I need to write and where to begin.
Step 2. Which Unit Test to Write First
Now that I have a list of required fields for my model and a list of functional requirements I can decide which unit test to write first. Since I am trying to follow the Test Driven Development approach, I will need to begin with a unit test that makes sure the Model structure exists. Otherwise, if there is no Model structure created, how can I validate that it contains the user’s first name and that the first name is valid?
The first unit test will be to test if the Model class or a struct can be created and exists.
class FormModelTests: XCTestCase { override func setUp() { // Put setup code here. This method is called before the invocation of each test method in the class. } override func tearDown() { // Put teardown code here. This method is called after the invocation of each test method in the class. } // Here you want to test that the model class or a struct can be created and that it has the correct structure func testFormModelHasRequiredFields() { let firstName = "Sergey" let lastName = "Kargopolov" let email = "[email protected]" let password = "12345678" let repeatPassword = "12345678" let signupFormModel = SignupFormModel(firstName: firstName, lastName: lastName, email: email, password:password, repeatPassword:repeatPassword) XCTAssertNotNil(signupFormModel) } }
For this unit test to even compile I will need to create a new Swift structure with the specified properties. It can be a new class or a new struct. I will create a new struct.
struct SignupFormModel { let firstName: String let lastName: String let email: String let password: String let repeatPassword: String }
Step 3. How Many Unit Tests to Write
In my experience, the number of unit tests I will need will be equal to or greater than the number of bulleted points written. It will be equal because I must test each functional requirement. But most likely it will be greater than that because as I go, then it is either new requirements come up or a realize that there is a new use-case I did not think about. For example, I will realize that I also need to make sure that:
- The provided password is not longer than 16 characters,
- The provided password must be alpha-numeric,
- The user password contains at least 1 capital letter.
As a result, the number of tests I write will almost always be equal to or higher than the things I initially write on paper.
Step 4. Test Coverage
Once I finish developing the feature I am working on using the TDD approach I will have enough unit tests written to see my feature working. The next step I usually do is check the Code Coverage in Xcode to see what has been covered and what I have missed.
I hope this short blog post was of some value to you. If you have time, share in the comments below how do you figure out the number of unit tests you need to write and how to figure which unit test to write first.
Before you go, check out other Unit testing tutorials on this blog. Hopefully, you will find other useful ones.
Happy unit testing! 🙋🏻♂️