Unit Testing For Beginners - Part One

What is Unit Testing?

We perform testing to check if specific functionality is working according to expectation or not. It is not limited to “functionality” only. In the Software Development field, we have different types of testings. Unit Testing means testing of “units”. In simple words, a unit may be a code block of functionality (example - method in OOP).

So is this a new type of testing?

No, every developer is doing this from his/her first program. As a developer, when you write a function, how do you check (test) if it is working fine? You try with some inputs and see if the function is providing the expected results or not. Sometimes, you run the application and perform different prerequisite steps to reach the stage/screen where you can perform testing of that functionality.
For example, suppose you have written the code of the “Like” button. Now, to test/debug if the “Like” button is working as expected, you will have to run the application. You will have to log in, you will have to go to a specific post (for example), and then you may test the “Like” button. This can be very time consuming depending on the steps. OR sometimes, we may call that specific function directly from our startup code by hard coding things (to avoid all dependencies) and then can do debugging to check if everything is working fine or not.
If you follow any of the above approaches, you are already doing “Unit Testing” of your code. In other words, every developer does manual “Unit Testing” of their code.

Do we do “Unit Testing” of our code only?

It is not limited to code only. You test your database queries, stored procedures, functions, etc. You test your front-end functionality as well.

What are we talking about if we are already doing Unit Testing in our daily life?

The above mentioned approaches may consume a lot of time. And what about if you make a change in some function? Will you do the debugging and testing of that function again with possible scenarios? We need some tools and automation here.
Now, we’ll see more details about Unit Testing. Unit Testing is a White Box testing technique. “White Box” means you do your testing after analyzing the internal implementation of “Unit”. You write code to test your unit (code). It is normally done by developers. Also, we don’t consider “external dependencies” like Databases, File System, Network, etc. when we do “proper” unit testing.

How do we write “Unit Tests” and what is Automation?

We use some tools or testing frameworks so that the management and execution of all test cases (in the future) will be easier. Also, automation will be easier to do. Automation is to perform a task without manual intervention. You can automate the execution of your “Unit Tests”. When you will make changes in your application, all test cases may be “executed” automatically on a daily basis (for example) to make sure if everything is working fine or not. Imagine if you have to test each function manually (to check if the existing functionalities are working fine) after any change in the application?

What are the external dependencies and why don’t we consider them in Unit Testing?

External dependency can be anything (other than function internal logic) on which your function execution is dependent. For example, your function might be communicating with a database or reading/writing a file or calling a 3rd party API for some verification, etc. Now, if any such dependency is not working correctly, your function will not work correctly but the purpose of “unit testing” is to test your function, not that specific dependency. It doesn’t mean we’ll not check that dependency at all. We’ll check that dependency in separate test cases. Also, we test our function with dependency and that is called “Integration dependency”.

But is it easy to write “Unit Tests” without external dependencies? 

No, it is not easy and will confuse you in the start. You will have to change your development style. You will have to write a code in a way that “external dependencies” should be replaceable without changing the internal logic of your function. This is done using “Dependency Injection”. You will have to understand & practice SOLID design patterns. Yes, Unit Testing is going to give you some pain but you can notice the improvement in your coding/thinking style even before you start writing unit tests.

So I should not start writing Unit Tests without improving my code?

No, you should start writing your “Unit tests” for simple cases or wherever possible for you without doing any refactoring. But also, start working on refactoring & start writing “unit test” friendly code. Don’t start spending so much time in unit testing in the beginning.

Why should I use a unit testing framework and which is recommended?

You can write your “Unit Test” without any framework. For example, you want to test a function. You can create a class object and then call the function by providing different inputs and then can check if the expected results are coming or not. But what if you would have hundreds of such functions to test? Yes, you can write code and test any function whenever you will write a function. But how will you execute them at once or how will you know which function is working fine and which is not working fine etc? Yes, you can write your code to manage your “Unit Tests”. And with time, more cases will come and you will keep adding more code to manage “Unit Tests”. So, why not use existing unit testing framework & tools for this? Yes, you should use existing popular & stable frameworks instead of wasting time in writing your own framework.
Depending on your technology, there are different Unit Testing frameworks available. xUnit is the collective name for several unit testing frameworks that derive their structure and functionality from Smalltalk's SUnit. [Ref: Wikipedia]. Many Unit Testing frameworks are following xUnit as reference. NUnit is such a framework. NUnit is an open source unit testing framework for .NET based applications. Jasmine & Mocha are famous JavaScript testing frameworks. These frameworks allow you to write test cases in them and then execute one by one or all at once. You may also automate the execution of your test cases in these frameworks.