Everyone will agree, software testing has an important place in software development. But why is that? The usual answer is that it helps us maintain the correctness of our software. That may be to test new code works as intended, but also that our new change didn’t cause a mistake somewhere in the previously existing code. However, that is not all. One often overlooked benefit is that it can help us write cleaner code, and in the rest of this article, you can read my thoughts on how unit tests help us do just that.
There are quite a few different types of testing. And when talking about testing, it is important to know which type we are talking about. Some types are:
Unit testing — this type tests the smallest possible part of code independent of other areas. You give the required input and test what is the output based on that
Integration testing — a type of testing where you take multiple different and connected parts of code and test how those work together
End-to-end — this is the type where you would test the whole application with all its parts connected. That might include clicking along UI causing different interactions with the server and checking how it all behaves
There are more types but in this article, I am focusing on unit testing.
As mentioned above, unit tests are used for testing small and independent pieces of functionality. A function for example. You call a function with required parameters and observe result changes based on those given parameters.
To have good and efficient unit tests there are some things you might keep in mind. The first one, and maybe the most important one is to make functions pure.
If you are not familiar with the term, for a function to be pure it needs to satisfy two requirements:
Given the same set of arguments, the return value doesn’t change
The function has no side effects
If that doesn’t make much sense, the following might be a bit simpler. A function is pure if the result of the function doesn’t change unless you change the parameters it is called with. Also, the function does not access or modify any data outside of its scope.
And now we are getting to the part about how unit tests help you improve your code.
The first step of improvement is function purity mentioned earlier. Those are a good idea in general as they are easy to refactor and move around. But when writing unit tests, you might get into a problem of mocking too many things or generally having difficulty mocking things it depends on. That is a good indicator your function is not pure and instead of spending time trying to make the test work, you might spend time improving your function.
The next thing your unit test might point out that needs to be improved is the size of functions. You might be tempted to add just one more thing inside your code. One more parameter to make it more generic. With time, it just keeps growing and becomes quite complex. When you are in a situation where you need to write many tests with different parameters for the same function, that is a good indication your code became too complex and you should consider splitting it into smaller pieces.
When writing code, many developers just add linting with some good rules, and as long as it passes it is ok. Many overlook tests as the way to improve it and believe those are just there to make sure nothing broke. While this article points at two very simple areas, I do believe they are important to keep in mind. And use them as guidelines to possible improvements in your code.