Skip to main content

Unit Testing

What is Unit Testing?
Unit testing means “Testing smallest logic that we can test isolating from other”.
Bit technical definition, let’s try to make it simple.

Every system/application consist of one or more modules each one of which will in turn contain sub modules. For building those sub modules we create many classes containing functions/methods which perform specific actions.
  • In Unit Testing we write code (test methods) which will test those functions on behalf of us. We write test method for every function in our application which has some important logic.When function (piece of code block) won’t satisfy our requirement, unit test will fail.
  • We write and conduct unit tests in development phase.
  • In Unit Testing one test will look into the only one unit (requirement – every smallest requirement) of software system and hence it is termed as unit testing.

What are its benefits? 

In simple words 
“Calculator does fast and efficient calculation than manual human calculation.”
If you ask someone to get the answer for 9*8, he/she won’t take more than 2 sec for that. But if you ask the same person to get the result for 999*888, not only you will see a huge difference in response time but also you will not be sure about the correctness of output.
If you consider using calculator for achieving the same, you will notice that for every input we feed output will be quick and it will be more reliable.

What we do when we develop something?

When developers do manually testing of the code they have written the biggest problem is they (testing logic/process) will not be reusable. We are in the IT world so job switch is very common among developers and there is a big possibility that person who developed something and person who is modifying it are different.
Let’s talk about a scenario. Let’s say company asks Developer 1 to develop a Maths library.
Step 1 - Developer1 creates following code.
public class CustomMaths
{
 public int Number1 { get; set; }
 public int Number2 { get; set; }
 
 public CustomMaths(int num1,int num2)
     {
          Number1 = num1;
         Number2 = num2;
     }
 public int Add()
     {
  return Number1 + Number2;
     }
 public int Sub()
     {
  return Number1 - Number2;
     }        
}  
Step 2 – Test the logic
Developer1 will test both Add and Sub function and confirms that everything is working fine.
Is it end - ?
No, Sometime later Developer 1 leave the organization and Developer 2 join as a replacement. Company demands him to add a new functionality to the Maths Library. They wants to add Div functionality and ask Developer 2 to make sure that DivideByZeroException is handled. (In short they also want to add zero validation to Numbe2)
Resulting Code ->
public CustomMaths(int num1,int num2)
{
 Number1 = num1;
 if (num2 == 0) { Number2 = 1; }
        else { Number2 = num2; }
}
.
.
.
public int Div()
{
 return Number1/Number2;
}
Now Developer2 will just test Div function and he will be in an impression that Add and Sub function are intact and work properly.
If you notice properly then you can understand
  • Add and Sub function are internally using Number1 and Number2 variable.
  • Number1 and Number2 are getting used in constructor.
  • Constructor is modified in order to make Div function behave correctly.
  • It means there is a possibility that Add and Sub functionality will also behave in unexpected manner.
  • Finally it means Developer2 also need to test Add and Sub function (which he/she is not doing right now.)
Will proper documentation work out here? 
Let’s say Developer1 will create some kind of document after the first release which explains how things need to be tested.
In real life it’s not possible. Developer1 will test Add and Sub functions using his thoughts. Let’s say he documented each and every step, which need to be followed while testing. But how should we make sure that Developer 2 follow all the steps properly. There is high possibility that Developer2 is not as smart as Developer1.
The Best solution will be Developer 1 will write some code,
  • Which will test Add and Sub Function
  • Which developer 2 will execute and confirms test is passed and so confirms function is working properly.
And that’s were Unit Test comes to picture.
Developer 1 will create a fast and reliable test methods which will be reused in every coming releases.
Note:There is a common misconception among developers. They think it takes more time to write code with unit test cases, and we don’t have time for that – In reality, unit testing would save your development time in the long run.

A simple example of unit testing using Visual studio

You will get tons of article on same, but I think better if we have a small demonstration here so that all food items will be in one plate.
Developer 1 Task
Step 1 - Create CustomMaths class library (just like above) with two functions Add and Sub
Step 2 - Create Unit Testing Project as Follows
Step 3- Add reference of previous class library to this newly created project
Step 4 - Create Test class has follows
[TestClass]
public class TestMathsClass
{
     [TestMethod]
 publicvoidTestAdd()
     {
  //Arrange
  CustomMaths maths = new CustomMaths(6, 5);
 
  //Act
  int result = maths.Add();
 
  //Assert
  Assert.AreEqual<int>(11, result);
     }
 
     [TestMethod]
 public void TestSub()
     {
  //Arrange
  CustomMaths maths = new CustomMaths(6, 5);
 
  //Act
  int result = maths.Sub();
 
  //Assert
  Assert.AreEqual<int>(1, result);
     }
} 
Explanation – As you can see Unit Testing follows simple three steps.
  • Arrange - Create objects and prepare everything needed to test functionality
  • Act – Execute and get the output
  • Assert – Compare final output with expected Output
Step 5– Build your solution and open test explorer window from Test > Windows > Test Explorer
Step 6– Right click Test cases and say Run Selected Tests.
Note: In the example we are using hard coded values (5 and 6) for testing but in real life scenario we will not use hard coded values rather will use some kind of data source like excel or database for input parameters and return value.

What makes Unit Test a good Unit Test?

I think now you are good with following things
  1. What is Unit Testing?
  2. Why we should we do it?
  3. How to do it?
So I think after this WWH (What, Why and How) it’s to time to learn how to write a good Unit Test.
In Database world any sql developer can go and create database but the person who know normalization well can develop and design database which will not contain any redundant data.
In the same manner any developer can go and write Unit Test but we cannot call every Unit Test a good unit test. Following are the key points which every Unit Test must have.
  1. Performance – Unit test must be very fast. It should not take much time to execute.
  2. Easy Setup–Writing lots of code for testing your logic is not a good practice. You should not end up with something where one logic will test another logic. Remember you are trying to test something which is complicated and make sure that your test method is very simple.       a.  Arrange everything which is required to test our logic.
          b.  Act on it by invoking our logic.
          c.  Assert and confirm whether output is matching to the expected output or not.
  3. Result oriented–Test should always pass or fail. There must be a result. There should not be any intermediate halt.
  4. Order Independent– Every Test method should be independent of every other test method. Test methods should not share states among them. So the order in which test methods need to be execute should not be fixed. One can go and execute any method anytime and it will either fail or pass.
  5. Reusable – Test methods should be reusable. I feel it’s the most important feature every test method should have. We should create Unit Tests which will be more beneficial in future. Changes are integral part of any application development. But with every change we should not re cerate the Unit Test rather we should reuse.
  6. Single Logic Test – Every test method should test only one Unit of Work. If it is testing more than behavior it’s not proper.
  7. Less dependencies– Test method should be completely isolated from External dependencies (like Mail Server, other classes) and Environmental dependencies (like current date time).
  8. Meaningful – We should not write test methods for each and every logic in our application. Our Test method should be valuable and meaningful. It should be worth. For example in real life scenarios we should not write test method which will test addition logic. J. In simple words write test methods for only those logic which you really want to test and which you feel worth to be tested.

Untestable code?

Code which violates above principles can be considered as Untestable code.
There is a very good saying by great leader of our IT world “If you system is easy to Unit Test it will be easy to maintain code.” 
Except “Less dependencies” point all can be managed and handled by developer easily. Proper understanding of SOLID principles lets design a system which will adhere to all of these 7 principles.
You can read about SOLID principle in detail
here.
We are in the world of object oriented programming and so we will talk in terms of real time objects. Objects interact with each other by calling methods and this is what we call as dependency.
  
Sometimes we also have dependencies to some environmental factors like system date time, File access rights etc. which can also make our code untestable.

How dependencies really affect Unit Testing? 

Let’s discuss the scenario shown in above diagram. We have CustomerMiddleLayer class with a SaveCustomer function. Purpose of this function is to add a new customer entry to database and on successful insert send an email to Administrator.
Before we go and create Test Method for SaveCustomer Method let’s try to think what happen when our email server is not configured properly or when we don’t have email server on test environment?
The answer is Test method will always fail regardless of what result our database access layer generates. This makes our “Save customer”logic completelyuntestable. We will be sure about the fact that email server will be configured well in later stage and so for now we just want to make sure that other things in the “Save customer” function is working properly but we are not able to do it.

Popular posts from this blog

Creating package in Oracle Database using Toad For Oracle

What are Packages in Oracle Database A package is  a group   of procedures, functions,  variables   and  SQL statements   created as a single unit. It is used to store together related objects. A package has two parts, Package  Specification  and Package Body.

Resolving 'Setup Account Privileges' error while installing SQL Server

A new installation of Microsoft SQL Server 2012 or Microsoft SQL Server 2008 R2 fails You see the following error message when you try to install a new instance of SQL Server 2012 or SQL Server 2008 R2: Rule "Setup account privileges" failed.

Creating Oracle stored Procedures using TOAD for Oracle

In a database management system, a  stored procedure  is a set of Structured Query Language (SQL) statements with an assigned name that's stored in the database in compiled form so that it can be shared by a number of programs. The use of  stored procedures  can be helpful in controlling  access to data, preserving  data integrity  and  improving  productivity.