Saturday, February 13, 2010

Why do we need unit tests?

Alright ... the TDD & CI analogy is good. Makes sense the way it is described. But how would you justify spending time and money on writing unit tests when you are under tight budget schedules. Why would you even need unit testing when we have a v good QA and Testing team and as good processes in place? This is an often asked question. Here is what I think.

Unit tests are not meant to rule out the need for QA / Testing. Unit testing is not even meant to complement QA / Testing, although they would help significantly reduce the burden on QA team. They are there for the developers. Let me give you an example - but first, put on your developer caps. I have a BaseDao class that has a query method on it like this:

public List<Object> query(String sql)

The method takes a SQL query as input and returns back a list of objects mapped from the query result set. The more important part is that the method returns a null back if no records were found in database. Now I have atleast 20 DAO's that extend this BaseDao and use this query method atleast 100 times.

Now in all good mind and after lot of consideration it was decided that the query method in the BaseDao will have to return a empty list (new ArrayList<Object>()) back instead of null if no records were found in database. Sounds like a easy change, but now what happens to all the 100 methods out there using this method? What happens to all those if conditions with null checks after the query method? For example: One of the DAO's has these lines of code that will break for sure.

List<Object> l = query("SELECT * FROM PERSON")
if(l == null)
  return false;
else
 return true;

How does a QA / Testing team plan to test this change in the system? This would become even interesting if there is a DAO method among these 100 that will be called only rarely in certain special data combinations only. Does the testing / QA team know what that method is and when is it called? The real idea with unit testing is to help the developers. If we have all these 20 DAO's and 100 methods all tested well it will be easy to find where the code would break when such a change takes place.

Another important point is that these lines of code continue to live as long as the system lives. The QA / Testing team moves on and the next time there is a new feature development / major bug fix the same QA team may not be there even. Even the same developers wont be there working on the system. Now consider this scenario - as a new developer you are put on such a project and you have to fix a defect. This method you need to fix is being used by 10 different classes from web and batch projects. How can you update this method confidently without breaking the functionality offered by all the other 10 classes? And you need to think of this even before the next QA / Testing team comes in to start testing the system.

Of course for developers, just like any other technology, there is a learning curve and it can be difficult. Specially with tight deadlines and with agile processes you may not get a lot of time to learn TDD. But who said life would be easy. Once the learning curve is conquered things become easy.

Tuesday, January 26, 2010

TDD and CI - An Analogy

More often unit tests are considered to be time consumers, lines of code that add no real value to the core working of the system. Business Requirements have a first class place in the project as well as the "real" code but unit tests do not get such a place as often as they deserve.

Lately in my work I have to do lot of convincing and mentoring developers on TDD & CI and encourage them to write more unit tests. To convince and to justify the need for TDD and more unit tests and CI I came up with this analogy.

In my analogy consider the lines of "real" code that do business logic or UI logic or data access logic as the people in society. As there are good and bad elements of the society so are good and bad code modules and lines of code. As people we tend to take different roles and actions in day to day life. We drive, we go out to eat, we take a walk in park, we shop. So do these lines of code in the system take different contexts. The same method in a DAO or Service class may be used by a Web frontend or by a batch job. Some of the domain objects may be used by the UI in a certain way and persisted in database or other remote stores.

Now lets talk about the business requirements. To keep people behave well and in sanity laws are formed. Some are explicit - such as the driving laws and some are implicit - well, we don't toss burgers in a restaurants, its bad manners. The business requirements for a system are such laws that the code needs to adhere to. The code must satisfy the requirements.

Here is the fun part - In the society we have cops and agents that enforce these laws on the society. What do we have in software applications that enforce these requirements? This is where TDD, CI and even BDD comes in. It enforces that our code behaves well. If a line of code breaks a unit test it means it violated the law (the business requirements) in some way and this line of code must of brought to justice. Without unit tests we can only assume that the lines of code will behave, but what happens when a change in requirement comes up and we change the code without enforcing the new and old laws?

There can be an argument that functional testing is a good way to enforce the requirements. This can be true to a certain extent. The part of this that worries me are two things. One is that functional testing is performed at specific milestones in the project cycle. The lines of code live on after this milestone has passed and often times these lines of code change without anymore functional testing. Will it help if the cops come in a city only once a month and assumes that things are well in the city rest of the days? The second trouble is that it is not guaranteed that functional testing will cover all lines of code. Well good functional tests would at some point cover lines of code but where is the metric?

The point to be taken here is that write unit tests - these are the cops of your code. If some other developer comes and changes these lines of code and unknowingly causes them to be bad elements of the software society the cops (unit tests) will catch em.

Wednesday, January 20, 2010

Long Time !!!

It has been quite a busy time the last 4 months. My little baby girl was born on Jan 11 and that marks a major milestone in the life. As the sleepless nights settle I would start blogging more.