Over the past few decades computer programming industry has been going through a complete revolution. The history of computer programming is not very old as compared to some of the other fields such as Architectural engineering, Astronomy, Chemistry etc. Unfortunately while we have observed an extremely fast growth rate in the hardware side; software development has not been as profound. If you are a software developer who has been in this industry for over 3 years, chances are that you would have heard, seen and maybe even part of some incredibly complex and large software that took years of development but in the end did not meet the expectations of your client.
Through the development process you had given it everything from late sittings to skipping lunch and in the worst case, sleeping in the office overnight 🙂
Even after all that much effort and commitment you often found yourself in situations where you would make a small change to the system and test everything you had done and deploy your code but the next morning someone would come running into your cubical and tell you that your code has broken their code. I am sure if you have been in the industry for long enough you know what I am talking about!
At moments like these you will sit there sitting how on earth could you have affected his code and why could you not find it the day before? The answer to these questions is a bit tricky and lies in multiple things, but the one thing that I want to focus in this article is our mechanism of testing.
Why unit testing?
If you have done any kind of manual testing you know that it is extremely boring and seemingly worthless. As programmer when you develop something you just can’t accept that it can be broken, that’s why they hire testers 🙂 Even for the testers it’s really hard to re-run the same tests day and night and to repeat that process over and over again for time span of years.
This is where dare may I say:
Software industry did not teach us a proper way of developing enterprise level software till very recently
In the recent past though we have found a solution to deliver quality software that work just the way our clients want them to and for us to do our daily development without worrying about unforeseen consequences. The secret ingredient to cooking great software nowadays is “Unit Testing”.
What are unit Tests?
A unit test in very simple words is the smallest testable part of the application that can be run automatically. When you run the unit test it shall either pass or fail. If the unit test passes than that means that the piece of code that the unit test verifies is working correctly. If the unit test fails than that means that something is wrong with your code. If the unit test fails ideally you should not need to debug and step into your application because the unit test should be very small and precise and should be testing only one thing, this would mean that you should immediately find out the reason for the test failing and be able to fix it!
Imagine if your application had thousands of those small unit tests written by every developer to test their own piece of code and you had the luxury of running all of those tests by the stroke of a key. Can you imagine what great impact it would have on your productivity and confidence?
Every time you would make a small change to the code, you can re-run all the tests and verify that the application is working correctly. If you break something you know that only the few lines of code that you have written right now are the culprit and thus it is very easy to fix the problem.
To achieve this point you need to learn few other things such as mocking and some design principles that help you write loosely coupled code and to put the icing on the cake you need to learn how to write clean code so that you spend more time developing new features rather than grasping old code that was written by you or someone else in the past, but don’t worry I have got it all those things covered in this blog right 😉
Characteristics of a good Unit Test
A good unit test normally has some characteristics that make it stand out. Typically a unit should meet the following conditions:
- A unit test should always be fully Automated
- A unit test should never be needed to run in a specific order. You should be able to run it anytime and in any order and it should be conclusive.
- Should be decisive and not give different results at different time or in different conditions
- Unit tests should run in memory. That means that tests need to interact with database should be run separately (Those are integration tests).
- Unit test should be very fast. Imagine running thousands of tests every minute and each of them takes 2 seconds to run. Well you can say good bye to unit testing right there. J
- Unit tests should be readable. If you have to spend a lot of time understanding what a unit test is doing then they lose their benefit.
- Unit tests need to be maintainable. You need to understand that unit tests are not third class citizen. They are as vital as your real productions code and if you will have hard time maintaining them then chances are that you will stop using them which will ruin the initial intention of testing your entire application using unit tests.
- Your unit tests need to be trustworthy, which means that if the pass you know your code works. They should act as a flag to whether you commit your code to production or not? As a developer you need to have faith in unit tests just like your religion.
What is Test Driven Development
Now that we understand what does unit testing mean we can establish what Test Driven Development (TDD) is? TDD as the name implies is simply a technique of software development in which you let unit test drive your code. In short in TDD:
- You write a unit test that fails
- Then you write only the amount of code that is needed to make that unit test pass
- Once you make the test pass you refactor your code and make it more readable and maintainable
These three steps are also known as the Red, Green Refactor steps. This sounds ridiculously simple right? Well in actuality it is, but the amount of benefit that you can gain from writing code strictly in this manner is huge.
What benefits can we achieve from TDD?
With TDD you get all the benefits of Unit Testing plus some additional benefits. Because you are following three very small steps your focus is enormous and your productivity increases.
You only write the amount of code that needs to be written in order to make the test pass thus you are always following the YAGNI (You aren’t gonna need it) Principal. I have seen a lot of developers who will just be working on a class and will just write a lot of methods in it thinking they will come of use in the future. A classic example of this can normally be seen in classes for data access and I have seen developers just writing methods for Insert, Update, Delete etc even though they do not need them at that time, thinking that they will come of use later.
Because you are refactoring your code at the end of every iteration; you end up with a very fresh and well maintained code base. This alone has a huge impact on your code and makes you write code that is very easy to maintain and much more readable.
We have established the fact that in order to write code with complete confidence and authority, we have to adopt Unit Testing and eventually Test Driven Development. In modern age I see no other way of developing complex, enterprise level software. It takes time and some practice to adapt to these new concepts but trust me once you start adopting them, they will become your Oxygen! In the coming articles I will try to explain the types of unit tests and when to use them and also why we need mocking.