Efficient unit test

Unit test is the first point of verification where we test the functionality of the code developed daily. It is pertinent for the success of the solution to be tested properly at the basic functional level before it is tested for logical correctness.

What is a Unit test? And why are they important?

Let’s assume, we have a function foo() which performs the task of the addition of two numbers. This function can be termed as Unit and testing the functionality of the unit is called Unit test.

Now, as the functionality of the function foo() should only be adding two number but some developer makes the mistake of using subtraction operation instead of addition operator. If testing not done properly, this function will always evaluate the wrong response. This example looks dumb, but wait, what? We are developers and always do dumb mistakes, hence, testing code’s functionality by statement, branches, and functions via Unit testing ensures the solid foundation.

Let’s move to the testing strategies to keep in mind while writing efficient code!

Keep a separate Mock File

While doing functional testing, the most common issue is managing mock variables and objects copied over for the test cases as the code grows larger. If the code file being tested is not too large, then, it might make sense to put the mock variables and objects within the same file. As the code grows, the size of mock objects tends to grow which makes the tests less readable and manageable.

In order to write easy to follow test case, the mock objects should be placed in a separate file called mock file. By placing all the mock objects at a single place, we achieve following advantages:

  1. Eliminate the duplication of any mocked-up object.
  2. Single place of management, meaning, the same mock objects can be used to test code in other files which might require the same object in unit testing.

Write meaningful descriptions

When it comes to development, there is second-to-none thought that the code should be meaningful and self-explanatory. If a person cannot understand what you have written, that means you have failed that very purpose of development.

Often while testing the code, we tend to be sloppy. Vague descriptions of the test cases are the same as an unimportant variable/function declaration. For example, the following description (written in Karma – JavaScript Unit test Framework) shows how vague description can be:

The description above is not clear on what this test block would testing. Now, the description below would show the difference between a good explanation and a bad one:

** The code examples are from Karma but explanation is not necessarily application only to Karma testing.

Write separate test for each Branch/functionality

One of the bad practice while unit testing is that people tend to put all the test cases for a function within the same test block. This makes the test a disaster in terms of keeping track of what is covered and what is not. Generally, what process I follow and recommend to write manageable and traceable test:

  1. Write a describe [karma] block or test function [JUnit] for Green and Red path. Put all the related it [karma] blocks within it.
  2. Put all red, green path describe blocks/functions mentioned above in a single describe block/function for the code.

With the steps above, it becomes more evident that the function being tested is properly segregated into the respective test path. Moreover, it is easier for someone who is new to make sense of it.

Mock 3rd party Services

When we use any 3rd party service, the assumption is that service is well tested and stable. If we don’t mock any 3rd party service, there can be a good chance that it might hinder with the unit testing given we are only there to test the functionality of the function written. I follow two ways to solve it:

  1. As discussed above, the mocks for the 3rd party services can be put in the ‘mock’ file for the test being written. This can be helpful when you edit any related functionality in the future.
  2. reate a common test utility file in a shared space which contains mock for all the related 3rd party services.

One of the most common mistake I have seen with people/teams writing their unit test is that they don’t mock their external services such as Databases calls/connections primarily.

For instance, if a database call or connection is not mocked then the test would connect with database (real-time) and all the calls made would be saved in persistence. This kind of testing is not considered Unit testing rather some kind of hybrid Integration testing. Although, it can be a subjective thing to mock certain services or not, mocking services will be right way.

Conclusion

Unit testing is an important part of development, whether you follow Test Driven Development paradigm or not. Without a correctly written unit test, the functionality of the code cannot be trusted. Yes, you can always do manual testing but is it efficient? No! With properly written unit tests, developers know the intent of the code written.

I have been following the strategies written above in my daily development routine and it has improved my efficiency in coding and locating the cause of error/exceptions. This also have improved the performance of other developers in the team who have to write efficient unit test for their code. I hope this article is helpful to other developers like me.