I've seen many times that unit tests were hard to read and maintain. The Tests in which the preparation of the test did not fit on the monitor. The different parts of the test were mixed and obfuscated. Unit tests have to be clear and easy to maintain to bring us value.
Good programmers write code that humans can understand - M. Fowler (1999)
I think this quote tells us that we should focus on naming things, continuously refactoring and creating a class that has a single responsibility. The same rules we should apply to unit testing.
I want to give you a few pieces of advice on how we can write cleaner tests.
Let's go to examples
Our goal is to make sure when the user password is the expired application will generate a reset password token.
Bad Tests
We have many mock setups. In this, the arrangement part of the test is huge. This is a major issue that I've seen. At first glance, it’s hard to locate the method that we are testing. We have some hard-coded test data. The data format is not close to real data. This code is not easy to read for a human to understand what we are testing and how we are testing.
Lets fix it.
Fakers
The first thing we’ll do in our refactoring is getting rid of creating objects for testing in a non-elegant way. We will get rid of magic strings. We can extract the creation of objects like SignInCommand or UserAccount to static classes with a factory method. Test data to create these objects, we can use the Faker.NET library which gives the possibility to interfere with fake mail, phone number, first name etc.
As we can see in UserAccountFaker class. We have used Faker.NET to generate a fake email and first name. Generated that is closer to real compared to some ‘testtest’ phrases.
Then we used this faker in line 41.
Mock Setups
For me, mocking framework API not looks good. It is easy to lose context here and obfuscate test code. To improve readability and give context to the code the same as is in production code in tests we can use private methods. By creating a private method you can give a meaning-full name for this mock setup e.g
"TimePassage". Please compare the Good and Bad test examples now. I'm sure that you can see the difference in readability, cognitive load is lower.
A lot of private methods on the bottom of the file do not look good to me. How do I handle this? I will explain this in the next post from this series.
COUNTER ARGUMENTS
Writing each test in that way will take too much time.
Answer:
Using IDE you can extract classes, and methods, and create factory methods in seconds. I recommend that you familiarize yourself with the keyboard shortcuts and the capabilities of IDE Rider or Visual Studio + Resharper.
I would prefer to see all code on one screen not hiding implementations of mocks or fakers.
Answer:
The human brain can take a certain dose of information at a time, if the preparation of the test is too complicated it will be difficult for you to understand at a glance. You will have to read it multiple times to understand how it works. Which will drastically affect productivity. In my opinion, it is better to divide the code into smaller fragments and when we are curious about the implementation or suspect a bug, it enters the private method to see something in it.
Summary
In summary, by extracting data preparation to Fakers and naming setup mocks. We improve readability and understanding of unit testing. This is a bit of pragmatic advice that can be implemented in any project at any time.
Take care of your cognitive load and productivity. See you on the next article 💪💪💪
Top comments (0)